aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml17
-rw-r--r--.cirrus.yml154
-rw-r--r--.fuzzbuzz.yml2
-rw-r--r--.gitignore1
-rw-r--r--.python-version2
-rw-r--r--.travis.yml141
-rw-r--r--Makefile.am33
-rw-r--r--REVIEWERS (renamed from CODEOWNERS)23
-rw-r--r--build-aux/m4/bitcoin_find_bdb48.m425
-rw-r--r--build-aux/m4/bitcoin_qt.m43
-rw-r--r--build_msvc/bitcoin-qt/bitcoin-qt.vcxproj2
-rw-r--r--build_msvc/bitcoin_config.h17
-rw-r--r--build_msvc/bitcoind/bitcoind.vcxproj4
-rw-r--r--build_msvc/common.init.vcxproj57
-rw-r--r--build_msvc/common.vcxproj2
-rw-r--r--build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in3
-rw-r--r--build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj4
-rwxr-xr-xci/lint/04_install.sh14
-rwxr-xr-xci/lint/05_before_script.sh2
-rwxr-xr-xci/lint/06_script.sh14
-rwxr-xr-xci/test/00_setup_env.sh2
-rw-r--r--ci/test/00_setup_env_arm.sh2
-rw-r--r--ci/test/00_setup_env_i686_centos.sh7
-rw-r--r--ci/test/00_setup_env_mac.sh7
-rw-r--r--ci/test/00_setup_env_mac_host.sh10
-rw-r--r--ci/test/00_setup_env_native_msan.sh2
-rw-r--r--ci/test/00_setup_env_native_nowallet.sh6
-rw-r--r--ci/test/00_setup_env_native_qt5.sh4
-rw-r--r--ci/test/00_setup_env_native_tsan.sh1
-rw-r--r--ci/test/00_setup_env_s390x.sh1
-rw-r--r--ci/test/00_setup_env_win64.sh6
-rwxr-xr-xci/test/04_install.sh21
-rwxr-xr-xci/test/05_before_script.sh4
-rwxr-xr-xci/test/06_script_a.sh5
-rwxr-xr-xci/test/06_script_b.sh13
-rwxr-xr-xci/test/wrap-wine.sh20
-rw-r--r--configure.ac130
-rwxr-xr-xcontrib/devtools/gen-manpages.sh16
-rwxr-xr-xcontrib/devtools/security-check.py2
-rwxr-xr-xcontrib/devtools/test-symbol-check.py162
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml6
-rw-r--r--contrib/gitian-descriptors/gitian-osx-signer.yml5
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml19
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml6
-rw-r--r--contrib/guix/libexec/build.sh4
-rw-r--r--contrib/macdeploy/README.md22
-rwxr-xr-xcontrib/macdeploy/custom_dsstore.py59
-rw-r--r--contrib/macdeploy/fancy.plist32
-rwxr-xr-xcontrib/macdeploy/macdeployqtplus561
-rw-r--r--contrib/seeds/.gitignore1
-rw-r--r--contrib/seeds/README.md8
-rwxr-xr-xcontrib/seeds/makeseeds.py5
-rw-r--r--contrib/seeds/nodes_main.txt1535
-rw-r--r--contrib/signet/README.md19
-rwxr-xr-xcontrib/signet/getcoins.py36
-rwxr-xr-xcontrib/testgen/gen_key_io_test_vectors.py9
-rw-r--r--depends/README.md6
-rw-r--r--depends/config.site.in16
-rw-r--r--depends/funcs.mk4
-rw-r--r--depends/hosts/darwin.mk2
-rw-r--r--depends/packages/bdb.mk4
-rw-r--r--depends/packages/boost.mk39
-rw-r--r--depends/packages/native_b2.mk20
-rw-r--r--depends/packages/native_biplist.mk15
-rw-r--r--depends/packages/native_cdrkit.mk28
-rw-r--r--depends/packages/native_ds_store.mk5
-rw-r--r--depends/packages/native_mac_alias.mk4
-rw-r--r--depends/packages/packages.mk6
-rw-r--r--depends/packages/qt.mk69
-rw-r--r--depends/packages/zeromq.mk2
-rw-r--r--depends/patches/boost/unused_var_in_process.patch22
-rw-r--r--depends/patches/native_cdrkit/cdrkit-deterministic.patch86
-rw-r--r--depends/patches/qt/fix_mingw_cross_compile.patch25
-rw-r--r--depends/patches/qt/fix_qpainter_non_determinism.patch63
-rw-r--r--depends/patches/qt/mac-qmake.conf4
-rw-r--r--doc/JSON-RPC-interface.md11
-rw-r--r--doc/REST-interface.md12
-rw-r--r--doc/bips.md1
-rw-r--r--doc/build-freebsd.md112
-rw-r--r--doc/build-openbsd.md1
-rw-r--r--doc/build-osx.md33
-rw-r--r--doc/build-unix.md4
-rw-r--r--doc/dependencies.md12
-rw-r--r--doc/descriptors.md2
-rw-r--r--doc/developer-notes.md27
-rw-r--r--doc/files.md37
-rw-r--r--doc/fuzzing.md10
-rw-r--r--doc/man/bitcoin-cli.1116
-rw-r--r--doc/man/bitcoin-qt.1611
-rw-r--r--doc/man/bitcoin-tx.1117
-rw-r--r--doc/man/bitcoin-wallet.164
-rw-r--r--doc/man/bitcoind.1584
-rw-r--r--doc/release-notes-19776.md9
-rw-r--r--doc/release-notes-19988.md9
-rw-r--r--doc/release-notes.md379
-rw-r--r--doc/release-process.md18
-rw-r--r--doc/shared-libraries.md3
-rw-r--r--doc/tor.md7
-rw-r--r--share/qt/Info.plist.in8
-rw-r--r--share/setup.nsi.in2
-rw-r--r--src/Makefile.am20
-rw-r--r--src/Makefile.crc32c.include2
-rw-r--r--src/Makefile.qt_locale.include1
-rw-r--r--src/Makefile.test.include1183
-rw-r--r--src/Makefile.test_util.include2
-rw-r--r--src/addrdb.cpp20
-rw-r--r--src/addrdb.h20
-rw-r--r--src/addrman.h94
-rw-r--r--src/attributes.h15
-rw-r--r--src/base58.cpp4
-rw-r--r--src/base58.h4
-rw-r--r--src/bench/ccoins_caching.cpp2
-rw-r--r--src/bench/chacha_poly_aead.cpp9
-rw-r--r--src/bench/prevector.cpp12
-rw-r--r--src/bench/wallet_balance.cpp6
-rw-r--r--src/bitcoin-cli-res.rc4
-rw-r--r--src/bitcoin-cli.cpp198
-rw-r--r--src/bitcoin-tx-res.rc4
-rw-r--r--src/bitcoin-tx.cpp20
-rw-r--r--src/bitcoin-wallet-res.rc4
-rw-r--r--src/bitcoin-wallet.cpp26
-rw-r--r--src/bitcoind-res.rc4
-rw-r--r--src/bitcoind.cpp27
-rw-r--r--src/bloom.h13
-rw-r--r--src/chainparams.cpp69
-rw-r--r--src/chainparamsseeds.h1535
-rw-r--r--src/clientversion.cpp8
-rw-r--r--src/clientversion.h7
-rw-r--r--src/compat.h6
-rw-r--r--src/consensus/params.h2
-rw-r--r--src/core_io.h4
-rw-r--r--src/core_read.cpp90
-rw-r--r--src/crc32c/.appveyor.yml13
-rw-r--r--src/crc32c/AUTHORS2
-rw-r--r--src/crc32c/CMakeLists.txt43
-rw-r--r--src/crc32c/Crc32cConfig.cmake.in (renamed from src/crc32c/Crc32cConfig.cmake)4
-rw-r--r--src/crc32c/src/crc32c.cc6
-rw-r--r--src/crc32c/src/crc32c_arm64.cc23
-rw-r--r--src/crc32c/src/crc32c_arm64.h8
-rw-r--r--src/crc32c/src/crc32c_arm64_check.h (renamed from src/crc32c/src/crc32c_arm64_linux_check.h)26
-rw-r--r--src/crc32c/src/crc32c_benchmark.cc8
-rw-r--r--src/crc32c/src/crc32c_read_le.h16
-rw-r--r--src/dummywallet.cpp1
-rw-r--r--src/hash.h2
-rw-r--r--src/httprpc.cpp22
-rw-r--r--src/httpserver.cpp7
-rw-r--r--src/init.cpp75
-rw-r--r--src/init.h2
-rw-r--r--src/interfaces/chain.h29
-rw-r--r--src/interfaces/node.cpp303
-rw-r--r--src/interfaces/node.h3
-rw-r--r--src/net.cpp390
-rw-r--r--src/net.h172
-rw-r--r--src/net_processing.cpp607
-rw-r--r--src/net_processing.h88
-rw-r--r--src/netaddress.cpp11
-rw-r--r--src/netaddress.h2
-rw-r--r--src/netbase.cpp16
-rw-r--r--src/node/coinstats.cpp2
-rw-r--r--src/node/context.cpp1
-rw-r--r--src/node/context.h2
-rw-r--r--src/node/interfaces.cpp (renamed from src/interfaces/chain.cpp)350
-rw-r--r--src/node/transaction.h2
-rw-r--r--src/outputtype.h2
-rw-r--r--src/policy/feerate.cpp4
-rw-r--r--src/policy/feerate.h17
-rw-r--r--src/policy/fees.cpp29
-rw-r--r--src/policy/fees.h3
-rw-r--r--src/policy/policy.cpp24
-rw-r--r--src/policy/policy.h48
-rw-r--r--src/primitives/transaction.cpp2
-rw-r--r--src/primitives/transaction.h14
-rw-r--r--src/protocol.cpp1
-rw-r--r--src/protocol.h4
-rw-r--r--src/psbt.h8
-rw-r--r--src/pubkey.h11
-rw-r--r--src/qt/askpassphrasedialog.cpp27
-rw-r--r--src/qt/askpassphrasedialog.h1
-rw-r--r--src/qt/bantablemodel.cpp3
-rw-r--r--src/qt/bitcoin.cpp7
-rw-r--r--src/qt/bitcoin_locale.qrc1
-rw-r--r--src/qt/bitcoingui.cpp23
-rw-r--r--src/qt/bitcoingui.h4
-rw-r--r--src/qt/bitcoinstrings.cpp21
-rw-r--r--src/qt/bitcoinunits.cpp6
-rw-r--r--src/qt/createwalletdialog.cpp26
-rw-r--r--src/qt/forms/createwalletdialog.ui32
-rw-r--r--src/qt/forms/debugwindow.ui70
-rw-r--r--src/qt/forms/optionsdialog.ui11
-rw-r--r--src/qt/guiutil.cpp34
-rw-r--r--src/qt/guiutil.h52
-rw-r--r--src/qt/locale/bitcoin_af.ts147
-rw-r--r--src/qt/locale/bitcoin_am.ts11
-rw-r--r--src/qt/locale/bitcoin_ar.ts392
-rw-r--r--src/qt/locale/bitcoin_be.ts39
-rw-r--r--src/qt/locale/bitcoin_bg.ts123
-rw-r--r--src/qt/locale/bitcoin_bn.ts147
-rw-r--r--src/qt/locale/bitcoin_bs.ts3
-rw-r--r--src/qt/locale/bitcoin_ca.ts227
-rw-r--r--src/qt/locale/bitcoin_cs.ts160
-rw-r--r--src/qt/locale/bitcoin_cy.ts45
-rw-r--r--src/qt/locale/bitcoin_da.ts151
-rw-r--r--src/qt/locale/bitcoin_de.ts447
-rw-r--r--src/qt/locale/bitcoin_el.ts159
-rw-r--r--src/qt/locale/bitcoin_en.ts148
-rw-r--r--src/qt/locale/bitcoin_en_GB.ts437
-rw-r--r--src/qt/locale/bitcoin_eo.ts63
-rw-r--r--src/qt/locale/bitcoin_es.ts499
-rw-r--r--src/qt/locale/bitcoin_es_CL.ts123
-rw-r--r--src/qt/locale/bitcoin_es_CO.ts115
-rw-r--r--src/qt/locale/bitcoin_es_DO.ts65
-rw-r--r--src/qt/locale/bitcoin_es_MX.ts2235
-rw-r--r--src/qt/locale/bitcoin_es_VE.ts97
-rw-r--r--src/qt/locale/bitcoin_et.ts81
-rw-r--r--src/qt/locale/bitcoin_eu.ts41
-rw-r--r--src/qt/locale/bitcoin_fa.ts214
-rw-r--r--src/qt/locale/bitcoin_fi.ts473
-rw-r--r--src/qt/locale/bitcoin_fil.ts280
-rw-r--r--src/qt/locale/bitcoin_fr.ts699
-rw-r--r--src/qt/locale/bitcoin_gl_ES.ts147
-rw-r--r--src/qt/locale/bitcoin_he.ts633
-rw-r--r--src/qt/locale/bitcoin_hi.ts75
-rw-r--r--src/qt/locale/bitcoin_hr.ts154
-rw-r--r--src/qt/locale/bitcoin_hu.ts712
-rw-r--r--src/qt/locale/bitcoin_id.ts135
-rw-r--r--src/qt/locale/bitcoin_is.ts37
-rw-r--r--src/qt/locale/bitcoin_it.ts459
-rw-r--r--src/qt/locale/bitcoin_ja.ts209
-rw-r--r--src/qt/locale/bitcoin_ka.ts73
-rw-r--r--src/qt/locale/bitcoin_kk.ts15
-rw-r--r--src/qt/locale/bitcoin_km.ts37
-rw-r--r--src/qt/locale/bitcoin_ko.ts143
-rw-r--r--src/qt/locale/bitcoin_ku_IQ.ts31
-rw-r--r--src/qt/locale/bitcoin_ky.ts21
-rw-r--r--src/qt/locale/bitcoin_la.ts49
-rw-r--r--src/qt/locale/bitcoin_lt.ts125
-rw-r--r--src/qt/locale/bitcoin_lv.ts61
-rw-r--r--src/qt/locale/bitcoin_mk.ts25
-rw-r--r--src/qt/locale/bitcoin_ml.ts23
-rw-r--r--src/qt/locale/bitcoin_mn.ts53
-rw-r--r--src/qt/locale/bitcoin_mr_IN.ts15
-rw-r--r--src/qt/locale/bitcoin_ms.ts3101
-rw-r--r--src/qt/locale/bitcoin_my.ts7
-rw-r--r--src/qt/locale/bitcoin_nb.ts151
-rw-r--r--src/qt/locale/bitcoin_ne.ts13
-rw-r--r--src/qt/locale/bitcoin_nl.ts249
-rw-r--r--src/qt/locale/bitcoin_pam.ts49
-rw-r--r--src/qt/locale/bitcoin_pl.ts321
-rw-r--r--src/qt/locale/bitcoin_pt.ts396
-rw-r--r--src/qt/locale/bitcoin_pt_BR.ts477
-rw-r--r--src/qt/locale/bitcoin_ro.ts121
-rw-r--r--src/qt/locale/bitcoin_ru.ts480
-rw-r--r--src/qt/locale/bitcoin_si.ts19
-rw-r--r--src/qt/locale/bitcoin_sk.ts155
-rw-r--r--src/qt/locale/bitcoin_sl.ts461
-rw-r--r--src/qt/locale/bitcoin_sn.ts21
-rw-r--r--src/qt/locale/bitcoin_sq.ts61
-rw-r--r--src/qt/locale/bitcoin_sr.ts231
-rw-r--r--src/qt/locale/bitcoin_sr@latin.ts33
-rw-r--r--src/qt/locale/bitcoin_sv.ts155
-rw-r--r--src/qt/locale/bitcoin_szl.ts79
-rw-r--r--src/qt/locale/bitcoin_ta.ts163
-rw-r--r--src/qt/locale/bitcoin_te.ts29
-rw-r--r--src/qt/locale/bitcoin_th.ts41
-rw-r--r--src/qt/locale/bitcoin_tr.ts919
-rw-r--r--src/qt/locale/bitcoin_uk.ts525
-rw-r--r--src/qt/locale/bitcoin_ur.ts75
-rw-r--r--src/qt/locale/bitcoin_uz@Cyrl.ts75
-rw-r--r--src/qt/locale/bitcoin_uz@Latn.ts11
-rw-r--r--src/qt/locale/bitcoin_vi.ts143
-rw-r--r--src/qt/locale/bitcoin_yo.ts3
-rw-r--r--src/qt/locale/bitcoin_zh-Hans.ts53
-rw-r--r--src/qt/locale/bitcoin_zh.ts41
-rw-r--r--src/qt/locale/bitcoin_zh_CN.ts475
-rw-r--r--src/qt/locale/bitcoin_zh_HK.ts21
-rw-r--r--src/qt/locale/bitcoin_zh_TW.ts782
-rw-r--r--src/qt/locale/bitcoin_zu.ts15
-rw-r--r--src/qt/notificator.cpp5
-rw-r--r--src/qt/optionsdialog.cpp17
-rw-r--r--src/qt/optionsdialog.h2
-rw-r--r--src/qt/optionsmodel.cpp23
-rw-r--r--src/qt/optionsmodel.h8
-rw-r--r--src/qt/overviewpage.cpp1
-rw-r--r--src/qt/paymentserver.cpp1
-rw-r--r--src/qt/qrimagewidget.cpp44
-rw-r--r--src/qt/qrimagewidget.h4
-rw-r--r--src/qt/res/bitcoin-qt-res.rc4
-rw-r--r--src/qt/rpcconsole.cpp50
-rw-r--r--src/qt/rpcconsole.h7
-rw-r--r--src/qt/sendcoinsdialog.cpp19
-rw-r--r--src/qt/sendcoinsdialog.h2
-rw-r--r--src/qt/splashscreen.cpp4
-rw-r--r--src/qt/splashscreen.h2
-rw-r--r--src/qt/test/addressbooktests.h2
-rw-r--r--src/qt/test/rpcnestedtests.cpp89
-rw-r--r--src/qt/test/rpcnestedtests.h2
-rw-r--r--src/qt/test/wallettests.h2
-rw-r--r--src/qt/transactiontablemodel.cpp75
-rw-r--r--src/qt/transactionview.cpp18
-rw-r--r--src/qt/walletcontroller.cpp17
-rw-r--r--src/qt/walletframe.cpp20
-rw-r--r--src/qt/walletframe.h6
-rw-r--r--src/qt/walletmodel.cpp7
-rw-r--r--src/qt/walletmodel.h2
-rw-r--r--src/qt/walletview.cpp4
-rw-r--r--src/qt/walletview.h2
-rw-r--r--src/randomenv.cpp13
-rw-r--r--src/rpc/blockchain.cpp14
-rw-r--r--src/rpc/blockchain.h2
-rw-r--r--src/rpc/client.cpp9
-rw-r--r--src/rpc/mining.cpp45
-rw-r--r--src/rpc/misc.cpp2
-rw-r--r--src/rpc/net.cpp63
-rw-r--r--src/rpc/rawtransaction.cpp31
-rw-r--r--src/rpc/rawtransaction_util.cpp2
-rw-r--r--src/rpc/rawtransaction_util.h2
-rw-r--r--src/rpc/request.h2
-rw-r--r--src/rpc/server.h9
-rw-r--r--src/rpc/util.cpp9
-rw-r--r--src/script/descriptor.cpp4
-rw-r--r--src/script/interpreter.cpp6
-rw-r--r--src/script/sigcache.cpp6
-rw-r--r--src/script/standard.h2
-rw-r--r--src/secp256k1/.travis.yml4
-rw-r--r--src/secp256k1/README.md2
-rw-r--r--src/secp256k1/build-aux/m4/bitcoin_secp.m427
-rw-r--r--src/secp256k1/configure.ac15
-rw-r--r--src/secp256k1/src/ecmult_impl.h6
-rw-r--r--src/shutdown.cpp89
-rw-r--r--src/shutdown.h17
-rw-r--r--src/span.h37
-rw-r--r--src/sync.cpp88
-rw-r--r--src/sync.h24
-rw-r--r--src/test/addrman_tests.cpp2
-rw-r--r--src/test/amount_tests.cpp6
-rw-r--r--src/test/base32_tests.cpp19
-rw-r--r--src/test/base58_tests.cpp24
-rw-r--r--src/test/base64_tests.cpp19
-rw-r--r--src/test/coins_tests.cpp2
-rw-r--r--src/test/denialofservice_tests.cpp27
-rw-r--r--src/test/fuzz/addition_overflow.cpp4
-rw-r--r--src/test/fuzz/addrdb.cpp2
-rw-r--r--src/test/fuzz/addrman.cpp129
-rw-r--r--src/test/fuzz/asmap.cpp2
-rw-r--r--src/test/fuzz/asmap_direct.cpp2
-rw-r--r--src/test/fuzz/autofile.cpp2
-rw-r--r--src/test/fuzz/banman.cpp5
-rw-r--r--src/test/fuzz/base_encode_decode.cpp2
-rw-r--r--src/test/fuzz/bech32.cpp2
-rw-r--r--src/test/fuzz/block.cpp4
-rw-r--r--src/test/fuzz/block_header.cpp2
-rw-r--r--src/test/fuzz/blockfilter.cpp2
-rw-r--r--src/test/fuzz/bloom_filter.cpp2
-rw-r--r--src/test/fuzz/buffered_file.cpp2
-rw-r--r--src/test/fuzz/chain.cpp2
-rw-r--r--src/test/fuzz/checkqueue.cpp2
-rw-r--r--src/test/fuzz/coins_view.cpp7
-rw-r--r--src/test/fuzz/connman.cpp157
-rw-r--r--src/test/fuzz/crypto.cpp2
-rw-r--r--src/test/fuzz/crypto_aes256.cpp2
-rw-r--r--src/test/fuzz/crypto_aes256cbc.cpp2
-rw-r--r--src/test/fuzz/crypto_chacha20.cpp2
-rw-r--r--src/test/fuzz/crypto_chacha20_poly1305_aead.cpp2
-rw-r--r--src/test/fuzz/crypto_common.cpp2
-rw-r--r--src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp2
-rw-r--r--src/test/fuzz/crypto_poly1305.cpp2
-rw-r--r--src/test/fuzz/cuckoocache.cpp2
-rwxr-xr-xsrc/test/fuzz/danger_link_all.sh28
-rw-r--r--src/test/fuzz/decode_tx.cpp9
-rw-r--r--src/test/fuzz/descriptor_parse.cpp7
-rw-r--r--src/test/fuzz/deserialize.cpp197
-rw-r--r--src/test/fuzz/eval_script.cpp4
-rw-r--r--src/test/fuzz/fee_rate.cpp2
-rw-r--r--src/test/fuzz/fees.cpp2
-rw-r--r--src/test/fuzz/flatfile.cpp2
-rw-r--r--src/test/fuzz/float.cpp2
-rw-r--r--src/test/fuzz/fuzz.cpp38
-rw-r--r--src/test/fuzz/fuzz.h25
-rw-r--r--src/test/fuzz/golomb_rice.cpp2
-rw-r--r--src/test/fuzz/hex.cpp4
-rw-r--r--src/test/fuzz/http_request.cpp2
-rw-r--r--src/test/fuzz/integer.cpp4
-rw-r--r--src/test/fuzz/key.cpp4
-rw-r--r--src/test/fuzz/key_io.cpp4
-rw-r--r--src/test/fuzz/kitchen_sink.cpp2
-rw-r--r--src/test/fuzz/load_external_block_file.cpp4
-rw-r--r--src/test/fuzz/locale.cpp2
-rw-r--r--src/test/fuzz/merkleblock.cpp36
-rw-r--r--src/test/fuzz/message.cpp4
-rw-r--r--src/test/fuzz/multiplication_overflow.cpp4
-rw-r--r--src/test/fuzz/net.cpp33
-rw-r--r--src/test/fuzz/net_permissions.cpp2
-rw-r--r--src/test/fuzz/netaddress.cpp2
-rw-r--r--src/test/fuzz/p2p_transport_deserializer.cpp13
-rw-r--r--src/test/fuzz/parse_hd_keypath.cpp2
-rw-r--r--src/test/fuzz/parse_iso8601.cpp2
-rw-r--r--src/test/fuzz/parse_numbers.cpp2
-rw-r--r--src/test/fuzz/parse_script.cpp2
-rw-r--r--src/test/fuzz/parse_univalue.cpp4
-rw-r--r--src/test/fuzz/policy_estimator.cpp4
-rw-r--r--src/test/fuzz/policy_estimator_io.cpp4
-rw-r--r--src/test/fuzz/pow.cpp4
-rw-r--r--src/test/fuzz/prevector.cpp2
-rw-r--r--src/test/fuzz/primitives_transaction.cpp2
-rw-r--r--src/test/fuzz/process_message.cpp46
-rw-r--r--src/test/fuzz/process_messages.cpp10
-rw-r--r--src/test/fuzz/protocol.cpp2
-rw-r--r--src/test/fuzz/psbt.cpp4
-rw-r--r--src/test/fuzz/random.cpp2
-rw-r--r--src/test/fuzz/rbf.cpp3
-rw-r--r--src/test/fuzz/rolling_bloom_filter.cpp2
-rw-r--r--src/test/fuzz/script.cpp4
-rw-r--r--src/test/fuzz/script_assets_test_minimizer.cpp4
-rw-r--r--src/test/fuzz/script_bitcoin_consensus.cpp2
-rw-r--r--src/test/fuzz/script_descriptor_cache.cpp2
-rw-r--r--src/test/fuzz/script_flags.cpp12
-rw-r--r--src/test/fuzz/script_interpreter.cpp2
-rw-r--r--src/test/fuzz/script_ops.cpp2
-rw-r--r--src/test/fuzz/script_sigcache.cpp6
-rw-r--r--src/test/fuzz/script_sign.cpp4
-rw-r--r--src/test/fuzz/scriptnum_ops.cpp2
-rw-r--r--src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp2
-rw-r--r--src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp2
-rw-r--r--src/test/fuzz/signature_checker.cpp6
-rw-r--r--src/test/fuzz/signet.cpp4
-rw-r--r--src/test/fuzz/span.cpp2
-rw-r--r--src/test/fuzz/spanparsing.cpp2
-rw-r--r--src/test/fuzz/string.cpp2
-rw-r--r--src/test/fuzz/strprintf.cpp2
-rw-r--r--src/test/fuzz/system.cpp2
-rw-r--r--src/test/fuzz/timedata.cpp2
-rw-r--r--src/test/fuzz/transaction.cpp9
-rw-r--r--src/test/fuzz/tx_in.cpp2
-rw-r--r--src/test/fuzz/tx_out.cpp2
-rw-r--r--src/test/fuzz/txrequest.cpp2
-rw-r--r--src/test/fuzz/util.h82
-rw-r--r--src/test/interfaces_tests.cpp51
-rw-r--r--src/test/key_tests.cpp22
-rw-r--r--src/test/net_tests.cpp163
-rw-r--r--src/test/netbase_tests.cpp26
-rw-r--r--src/test/reverselock_tests.cpp10
-rw-r--r--src/test/script_p2sh_tests.cpp6
-rw-r--r--src/test/script_tests.cpp77
-rw-r--r--src/test/sync_tests.cpp90
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/test/util/logging.h2
-rw-r--r--src/test/util/net.cpp10
-rw-r--r--src/test/util/net.h2
-rw-r--r--src/test/util/setup_common.cpp75
-rw-r--r--src/test/util/setup_common.h24
-rw-r--r--src/test/util/validation.cpp22
-rw-r--r--src/test/util/validation.h17
-rw-r--r--src/test/util_tests.cpp58
-rw-r--r--src/test/validation_chainstatemanager_tests.cpp14
-rw-r--r--src/tinyformat.h4
-rw-r--r--src/torcontrol.cpp1
-rw-r--r--src/txmempool.cpp19
-rw-r--r--src/txmempool.h19
-rw-r--r--src/txrequest.cpp104
-rw-r--r--src/univalue/include/univalue.h6
-rw-r--r--src/univalue/test/object.cpp14
-rw-r--r--src/util/bip32.h2
-rw-r--r--src/util/check.h20
-rw-r--r--src/util/fees.cpp7
-rw-r--r--src/util/fees.h1
-rw-r--r--src/util/memory.h3
-rw-r--r--src/util/moneystr.h2
-rw-r--r--src/util/strencodings.cpp2
-rw-r--r--src/util/strencodings.h14
-rw-r--r--src/util/string.h6
-rw-r--r--src/util/system.cpp35
-rw-r--r--src/util/system.h8
-rw-r--r--src/util/time.h4
-rw-r--r--src/validation.cpp130
-rw-r--r--src/validation.h10
-rw-r--r--src/wallet/bdb.cpp45
-rw-r--r--src/wallet/bdb.h13
-rw-r--r--src/wallet/db.cpp117
-rw-r--r--src/wallet/db.h11
-rw-r--r--src/wallet/feebumper.cpp4
-rw-r--r--src/wallet/init.cpp10
-rw-r--r--src/wallet/interfaces.cpp (renamed from src/interfaces/wallet.cpp)31
-rw-r--r--src/wallet/load.cpp21
-rw-r--r--src/wallet/rpcdump.cpp11
-rw-r--r--src/wallet/rpcwallet.cpp281
-rw-r--r--src/wallet/salvage.cpp7
-rw-r--r--src/wallet/scriptpubkeyman.cpp16
-rw-r--r--src/wallet/scriptpubkeyman.h13
-rw-r--r--src/wallet/sqlite.cpp52
-rw-r--r--src/wallet/sqlite.h3
-rw-r--r--src/wallet/test/coinselector_tests.cpp5
-rw-r--r--src/wallet/test/db_tests.cpp7
-rw-r--r--src/wallet/test/init_test_fixture.cpp2
-rw-r--r--src/wallet/test/init_test_fixture.h1
-rw-r--r--src/wallet/test/ismine_tests.cpp3
-rw-r--r--src/wallet/test/scriptpubkeyman_tests.cpp4
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp4
-rw-r--r--src/wallet/test/wallet_test_fixture.h3
-rw-r--r--src/wallet/test/wallet_tests.cpp59
-rw-r--r--src/wallet/test/walletdb_tests.cpp29
-rw-r--r--src/wallet/wallet.cpp166
-rw-r--r--src/wallet/wallet.h33
-rw-r--r--src/wallet/walletdb.cpp38
-rw-r--r--src/wallet/walletdb.h1
-rw-r--r--src/wallet/wallettool.cpp44
-rw-r--r--src/wallet/walletutil.cpp46
-rw-r--r--src/wallet/walletutil.h6
-rw-r--r--src/warnings.cpp18
-rw-r--r--src/warnings.h2
-rw-r--r--test/config.ini.in2
-rw-r--r--test/functional/README.md2
-rw-r--r--test/functional/data/wallets/high_minversion/.walletlock0
-rw-r--r--test/functional/data/wallets/high_minversion/GENERATE.md8
-rw-r--r--test/functional/data/wallets/high_minversion/db.log0
-rw-r--r--test/functional/data/wallets/high_minversion/wallet.datbin16384 -> 0 bytes
-rwxr-xr-xtest/functional/example_test.py5
-rwxr-xr-xtest/functional/feature_abortnode.py4
-rwxr-xr-xtest/functional/feature_backwards_compatibility.py183
-rwxr-xr-xtest/functional/feature_bip68_sequence.py17
-rwxr-xr-xtest/functional/feature_block.py24
-rwxr-xr-xtest/functional/feature_config_args.py8
-rwxr-xr-xtest/functional/feature_csv_activation.py1
-rwxr-xr-xtest/functional/feature_fee_estimation.py13
-rwxr-xr-xtest/functional/feature_minchainwork.py4
-rwxr-xr-xtest/functional/feature_notifications.py19
-rwxr-xr-xtest/functional/feature_nulldummy.py31
-rwxr-xr-xtest/functional/feature_proxy.py67
-rwxr-xr-xtest/functional/feature_pruning.py30
-rwxr-xr-xtest/functional/feature_segwit.py5
-rwxr-xr-xtest/functional/feature_settings.py12
-rwxr-xr-xtest/functional/feature_taproot.py51
-rwxr-xr-xtest/functional/interface_zmq.py9
-rwxr-xr-xtest/functional/mempool_accept.py16
-rwxr-xr-xtest/functional/mempool_compatibility.py3
-rwxr-xr-xtest/functional/mempool_expiry.py52
-rwxr-xr-xtest/functional/mempool_persist.py6
-rwxr-xr-xtest/functional/mempool_spend_coinbase.py28
-rwxr-xr-xtest/functional/mempool_unbroadcast.py8
-rwxr-xr-xtest/functional/mining_basic.py17
-rwxr-xr-xtest/functional/mining_getblocktemplate_longpoll.py33
-rwxr-xr-xtest/functional/p2p_addr_relay.py37
-rwxr-xr-xtest/functional/p2p_blockfilters.py6
-rwxr-xr-xtest/functional/p2p_blocksonly.py2
-rwxr-xr-xtest/functional/p2p_compactblocks.py42
-rwxr-xr-xtest/functional/p2p_disconnect_ban.py14
-rwxr-xr-xtest/functional/p2p_feefilter.py3
-rwxr-xr-xtest/functional/p2p_fingerprint.py47
-rwxr-xr-xtest/functional/p2p_invalid_messages.py9
-rwxr-xr-xtest/functional/p2p_leak.py19
-rwxr-xr-xtest/functional/p2p_node_network_limited.py16
-rwxr-xr-xtest/functional/p2p_permissions.py36
-rwxr-xr-xtest/functional/p2p_segwit.py26
-rwxr-xr-xtest/functional/p2p_timeouts.py6
-rwxr-xr-xtest/functional/p2p_tx_download.py53
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py3
-rwxr-xr-xtest/functional/rpc_estimatefee.py4
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py204
-rwxr-xr-xtest/functional/rpc_getblockfilter.py5
-rwxr-xr-xtest/functional/rpc_getpeerinfo_deprecation.py3
-rwxr-xr-xtest/functional/rpc_invalidateblock.py5
-rwxr-xr-xtest/functional/rpc_net.py112
-rwxr-xr-xtest/functional/rpc_preciousblock.py7
-rwxr-xr-xtest/functional/rpc_psbt.py89
-rwxr-xr-xtest/functional/rpc_rawtransaction.py257
-rwxr-xr-xtest/functional/rpc_scantxoutset.py3
-rwxr-xr-xtest/functional/rpc_setban.py7
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py48
-rwxr-xr-xtest/functional/rpc_txoutproof.py2
-rwxr-xr-xtest/functional/rpc_users.py11
-rw-r--r--test/functional/test_framework/bdb.py152
-rw-r--r--test/functional/test_framework/blocktools.py56
-rw-r--r--test/functional/test_framework/key.py13
-rwxr-xr-xtest/functional/test_framework/messages.py1
-rwxr-xr-xtest/functional/test_framework/p2p.py9
-rw-r--r--test/functional/test_framework/script.py24
-rwxr-xr-xtest/functional/test_framework/script_util.py59
-rwxr-xr-xtest/functional/test_framework/test_framework.py86
-rwxr-xr-xtest/functional/test_framework/test_node.py19
-rw-r--r--test/functional/test_framework/util.py107
-rw-r--r--test/functional/test_framework/wallet.py17
-rwxr-xr-xtest/functional/test_runner.py42
-rwxr-xr-xtest/functional/tool_wallet.py90
-rwxr-xr-xtest/functional/wallet_abandonconflict.py6
-rwxr-xr-xtest/functional/wallet_address_types.py34
-rwxr-xr-xtest/functional/wallet_avoidreuse.py3
-rwxr-xr-xtest/functional/wallet_backup.py33
-rwxr-xr-xtest/functional/wallet_balance.py47
-rwxr-xr-xtest/functional/wallet_basic.py205
-rwxr-xr-xtest/functional/wallet_bumpfee.py135
-rwxr-xr-xtest/functional/wallet_createwallet.py55
-rwxr-xr-xtest/functional/wallet_descriptor.py10
-rwxr-xr-xtest/functional/wallet_dump.py7
-rwxr-xr-xtest/functional/wallet_hd.py7
-rwxr-xr-xtest/functional/wallet_import_rescan.py4
-rwxr-xr-xtest/functional/wallet_importdescriptors.py25
-rwxr-xr-xtest/functional/wallet_importmulti.py2
-rwxr-xr-xtest/functional/wallet_importprunedfunds.py53
-rwxr-xr-xtest/functional/wallet_keypool_topup.py9
-rwxr-xr-xtest/functional/wallet_labels.py4
-rwxr-xr-xtest/functional/wallet_listsinceblock.py23
-rwxr-xr-xtest/functional/wallet_listtransactions.py26
-rwxr-xr-xtest/functional/wallet_multiwallet.py128
-rwxr-xr-xtest/functional/wallet_reorgsrestore.py12
-rwxr-xr-xtest/functional/wallet_resendwallettransactions.py17
-rwxr-xr-xtest/functional/wallet_send.py90
-rwxr-xr-xtest/functional/wallet_txn_clone.py6
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py6
-rwxr-xr-xtest/functional/wallet_upgradewallet.py295
-rwxr-xr-xtest/fuzz/test_runner.py65
-rw-r--r--test/lint/README.md15
-rwxr-xr-xtest/lint/extended-lint-cppcheck.sh11
-rwxr-xr-xtest/lint/git-subtree-check.sh57
-rwxr-xr-xtest/lint/lint-circular-dependencies.sh1
-rwxr-xr-xtest/lint/lint-python.sh1
-rwxr-xr-xtest/lint/lint-rpc-help.sh24
-rwxr-xr-xtest/lint/lint-shell.sh3
-rw-r--r--test/sanitizer_suppressions/tsan2
-rw-r--r--test/sanitizer_suppressions/ubsan6
-rw-r--r--test/util/data/bitcoin-util-test.json2
619 files changed, 25948 insertions, 15009 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index eace0b7121..7250d4ad94 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -7,23 +7,24 @@ clone_depth: 5
environment:
PATH: 'C:\Python37-x64;C:\Python37-x64\Scripts;%PATH%'
PYTHONUTF8: 1
- QT_DOWNLOAD_URL: 'https://github.com/sipsorcery/qt_win_binary/releases/download/v1.6/Qt5.9.8_x64_static_vs2019.zip'
- QT_DOWNLOAD_HASH: '9a8c6eb20967873785057fdcd329a657c7f922b0af08c5fde105cc597dd37e21'
+ QT_DOWNLOAD_URL: 'https://github.com/sipsorcery/qt_win_binary/releases/download/qt598x64_vs2019_v1681/qt598_x64_vs2019_1681.zip'
+ QT_DOWNLOAD_HASH: '00cf7327818c07d74e0b1a4464ffe987c2728b00d49d4bf333065892af0515c3'
QT_LOCAL_PATH: 'C:\Qt5.9.8_x64_static_vs2019'
- VCPKG_INSTALL_PATH: 'C:\tools\vcpkg\installed'
- VCPKG_COMMIT_ID: '40230b8e3f6368dcb398d649331be878ca1e9007'
+ VCPKG_TAG: '2020.11-1'
install:
# Disable zmq test for now since python zmq library on Windows would cause Access violation sometimes.
# - cmd: pip install zmq
-# Powershell block below is to install the c++ dependencies via vcpkg. The pseudo code is:
+# The powershell block below is to set up vcpkg to install the c++ dependencies. The pseudo code is:
# a. Checkout the vcpkg source (including port files) for the specific checkout and build the vcpkg binary,
-# b. Install the missing packages using the vcpkg manifest.
+# b. Append a setting to the vcpkg cmake config file to only do release builds of dependencies (skipping deubg builds saves ~5 mins).
+# Note originally this block also installed the dependencies using 'vcpkg install'. Dependencies are now installed
+# as part of the msbuild command using vcpkg mainfests.
- ps: |
cd c:\tools\vcpkg
$env:GIT_REDIRECT_STDERR = '2>&1' # git is writing non-errors to STDERR when doing git pull. Send to STDOUT instead.
- git pull origin master > $null
- git -c advice.detachedHead=false checkout $env:VCPKG_COMMIT_ID
+ git -c advice.detachedHead=false checkout $env:VCPKG_TAG
.\bootstrap-vcpkg.bat > $null
+ Add-Content "C:\tools\vcpkg\triplets\$env:PLATFORM-windows-static.cmake" "set(VCPKG_BUILD_TYPE release)"
cd "$env:APPVEYOR_BUILD_FOLDER"
before_build:
# Powershell block below is to download and extract the Qt static libraries. The pseudo code is:
diff --git a/.cirrus.yml b/.cirrus.yml
index 5dc7e7995a..0507d664f1 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,24 +1,34 @@
### Global defaults
-timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out
-container:
- # https://cirrus-ci.org/faq/#are-there-any-limits
- # Each project has 16 CPU in total, assign 2 to each container, so that 8 tasks run in parallel
- cpu: 2
- memory: 8G # Set to 8GB to avoid OOM. https://cirrus-ci.org/guide/linux/#linux-containers
- kvm: true # Use kvm to avoid spurious CI failures in the default virtualization cluster, see https://github.com/bitcoin/bitcoin/issues/20093
env:
- PACKAGE_MANAGER_INSTALL : "apt-get update && apt-get install -y"
+ PACKAGE_MANAGER_INSTALL: "apt-get update && apt-get install -y"
MAKEJOBS: "-j4"
DANGER_RUN_CI_ON_HOST: "1" # Containers will be discarded after the run, so there is no risk that the ci scripts modify the system
TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache
CCACHE_SIZE: "200M"
CCACHE_DIR: "/tmp/ccache_dir"
-### Global task template
-
# https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks
+base_template: &BASE_TEMPLATE
+ skip: $CIRRUS_REPO_FULL_NAME == "bitcoin-core/gui" && $CIRRUS_PR == "" # No need to run on the read-only mirror, unless it is a PR. https://cirrus-ci.org/guide/writing-tasks/#conditional-task-execution
+ merge_base_script:
+ - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi
+ - bash -c "$PACKAGE_MANAGER_INSTALL git"
+ - git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH
+ - git config --global user.email "ci@ci.ci"
+ - git config --global user.name "ci"
+ - git merge FETCH_HEAD # Merge base to detect silent merge conflicts
+ stateful: false # https://cirrus-ci.org/guide/writing-tasks/#stateful-tasks
+
global_task_template: &GLOBAL_TASK_TEMPLATE
+ << : *BASE_TEMPLATE
+ timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out
+ container:
+ # https://cirrus-ci.org/faq/#are-there-any-limits
+ # Each project has 16 CPU in total, assign 2 to each container, so that 8 tasks run in parallel
+ cpu: 2
+ memory: 8G # Set to 8GB to avoid OOM. https://cirrus-ci.org/guide/linux/#linux-containers
+ kvm: true # Use kvm to avoid spurious CI failures in the default virtualization cluster, see https://github.com/bitcoin/bitcoin/issues/20093
ccache_cache:
folder: "/tmp/ccache_dir"
depends_built_cache:
@@ -27,15 +37,14 @@ global_task_template: &GLOBAL_TASK_TEMPLATE
folder: "/tmp/cirrus-ci-build/depends/sdk-sources"
depends_releases_cache:
folder: "/tmp/cirrus-ci-build/releases"
- merge_base_script:
- - bash -c "$PACKAGE_MANAGER_INSTALL git"
- - git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH
- - git config --global user.email "ci@ci.ci"
- - git config --global user.name "ci"
- - git merge FETCH_HEAD # Merge base to detect silent merge conflicts
ci_script:
- ./ci/test_run_all.sh
+compute_credits_template: &CREDITS_TEMPLATE
+ # https://cirrus-ci.org/pricing/#compute-credits
+ # Only use credits for pull requests to the main repo
+ use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'bitcoin/bitcoin' && $CIRRUS_PR != ""
+
#task:
# name: "Windows"
# windows_container:
@@ -53,18 +62,81 @@ global_task_template: &GLOBAL_TASK_TEMPLATE
# - choco install python --version=3.7.7 -y
task:
- name: 'x86_64 Linux [GOAL: install] [focal] [depends, sanitizers: thread (TSan), no gui]'
+ name: 'lint [bionic]'
+ << : *BASE_TEMPLATE
+ container:
+ image: ubuntu:bionic # For python 3.6, oldest supported version according to doc/dependencies.md
+ cpu: 1
+ memory: 1G
+ # For faster CI feedback, immediately schedule the linters
+ << : *CREDITS_TEMPLATE
+ setup_script:
+ - set -o errexit; source ./ci/test/00_setup_env.sh
+ before_install_script:
+ - set -o errexit; source ./ci/test/03_before_install.sh
+ install_script:
+ - set -o errexit; source ./ci/lint/04_install.sh
+ before_script:
+ - set -o errexit; source ./ci/lint/05_before_script.sh
+ lint_script:
+ - set -o errexit; source ./ci/lint/06_script.sh
+
+task:
+ name: 'ARM [unit tests, no functional tests] [buster]'
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: debian:buster
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_arm.sh"
+
+task:
+ name: 'Win64 [unit tests, no gui tests, no boost::process, no functional tests] [bionic]'
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:bionic
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_win64.sh"
+
+task:
+ name: '32-bit + dash [gui] [CentOS 8]'
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: centos:8
+ env:
+ PACKAGE_MANAGER_INSTALL: "yum install -y"
+ FILE_ENV: "./ci/test/00_setup_env_i686_centos.sh"
+
+task:
+ name: '[previous releases, uses qt5 dev package and some depends packages] [unsigned char] [bionic]'
+ # For faster CI feedback, immediately schedule a task that compiles most modules
+ << : *CREDITS_TEMPLATE
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:bionic
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_native_qt5.sh"
+
+task:
+ name: '[depends, sanitizers: thread (TSan), no gui] [focal]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
- cpu: 4 # Double CPU and Memory to avoid timeout
- memory: 16G
+ cpu: 4 # Double CPU and increase Memory to avoid timeout
+ memory: 24G
env:
MAKEJOBS: "-j8"
FILE_ENV: "./ci/test/00_setup_env_native_tsan.sh"
task:
- name: 'x86_64 Linux [GOAL: install] [focal] [no depends, only system libs, sanitizers: address/leak (ASan + LSan) + undefined (UBSan) + integer]'
+ name: '[depends, sanitizers: memory (MSan)] [focal]'
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:focal
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_native_msan.sh"
+
+task:
+ name: '[no depends, sanitizers: address/leak (ASan + LSan) + undefined (UBSan) + integer] [focal]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
@@ -72,9 +144,47 @@ task:
FILE_ENV: "./ci/test/00_setup_env_native_asan.sh"
task:
- name: 'x86_64 Linux [GOAL: install] [focal] [no depends, only system libs, fuzzers under valgrind]'
+ name: '[no depends, sanitizers: fuzzer,address,undefined] [focal]'
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:focal
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_native_fuzz.sh"
+
+task:
+ name: '[multiprocess] [focal]'
<< : *GLOBAL_TASK_TEMPLATE
container:
image: ubuntu:focal
env:
- FILE_ENV: "./ci/test/00_setup_env_native_fuzz_with_valgrind.sh"
+ FILE_ENV: "./ci/test/00_setup_env_native_multiprocess.sh"
+
+task:
+ name: '[no wallet] [bionic]'
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:bionic
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_native_nowallet.sh"
+
+task:
+ name: 'macOS 10.14 [gui, no tests] [bionic]'
+ << : *GLOBAL_TASK_TEMPLATE
+ container:
+ image: ubuntu:bionic
+ env:
+ FILE_ENV: "./ci/test/00_setup_env_mac.sh"
+
+task:
+ name: 'macOS 10.15 native [gui] [no depends]'
+ macos_brew_addon_script:
+ - brew install boost libevent berkeley-db4 qt miniupnpc ccache zeromq qrencode sqlite libtool automake pkg-config gnu-getopt
+ << : *GLOBAL_TASK_TEMPLATE
+ osx_instance:
+ # Use latest image, but hardcode version to avoid silent upgrades (and breaks)
+ image: catalina-xcode-12.1 # https://cirrus-ci.org/guide/macOS
+ env:
+ DANGER_RUN_CI_ON_HOST: "true"
+ CI_USE_APT_INSTALL: "no"
+ PACKAGE_MANAGER_INSTALL: "echo" # Nothing to do
+ FILE_ENV: "./ci/test/00_setup_env_mac_host.sh"
diff --git a/.fuzzbuzz.yml b/.fuzzbuzz.yml
index d44ac27eb9..7615eb3420 100644
--- a/.fuzzbuzz.yml
+++ b/.fuzzbuzz.yml
@@ -7,7 +7,7 @@ setup:
- sudo apt-get update
- sudo apt-get install -y autoconf bsdmainutils clang git libboost-all-dev libboost-program-options-dev libc++1 libc++abi1 libc++abi-dev libc++-dev libclang1 libclang-dev libdb5.3++ libevent-dev libllvm-ocaml-dev libomp5 libomp-dev libprotobuf-dev libqt5core5a libqt5dbus5 libqt5gui5 libssl-dev libtool llvm llvm-dev llvm-runtime pkg-config protobuf-compiler qttools5-dev qttools5-dev-tools software-properties-common
- ./autogen.sh
- - CC=clang CXX=clang++ ./configure --enable-fuzz --with-sanitizers=address,fuzzer,undefined
+ - CC=clang CXX=clang++ ./configure --enable-fuzz --with-sanitizers=address,fuzzer,undefined --enable-danger-fuzz-link-all
- make
- git clone https://github.com/bitcoin-core/qa-assets
auto_targets:
diff --git a/.gitignore b/.gitignore
index 5726b18928..810ef5db6b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@ src/qt/bitcoin-qt.includes
*.log
*.trs
*.dmg
+*.iso
*.json.h
*.raw.h
diff --git a/.python-version b/.python-version
index c49282585a..8b7b0b52e5 100644
--- a/.python-version
+++ b/.python-version
@@ -1 +1 @@
-3.5.6
+3.6.12
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 42fa653d8c..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,141 +0,0 @@
-# Travis caches can be manually removed if necessary. This is one of the very
-# few manual operations that is possible with Travis, and it can be done by a
-# Bitcoin Core GitHub member via the Travis web interface [0].
-#
-# Travis CI uploads the cache after the script phase of the build [1].
-# However, the build is terminated without saving the cache if it takes over
-# 50 minutes [2]. Thus, if we spent too much time in early build stages, fail
-# with an error and save the cache.
-#
-# [0] https://travis-ci.org/bitcoin/bitcoin/caches
-# [1] https://docs.travis-ci.com/user/caching/#build-phases
-# [2] https://docs.travis-ci.com/user/customizing-the-build#build-timeouts
-
-version: ~> 1.0
-
-dist: bionic
-os: linux
-language: minimal
-arch: amd64
-cache:
- directories:
- - $TRAVIS_BUILD_DIR/depends/built
- - $TRAVIS_BUILD_DIR/depends/sdk-sources
- - $TRAVIS_BUILD_DIR/ci/scratch/.ccache
- - $TRAVIS_BUILD_DIR/releases/$HOST
-stages:
- - lint
- - test
-env:
- global:
- - CI_RETRY_EXE="travis_retry"
- - CACHE_ERR_MSG="Error! Initial build successful, but not enough time remains to run later build stages and tests. See https://docs.travis-ci.com/user/customizing-the-build#build-timeouts . Please manually re-run this job by using the travis restart button. The next run should not time out because the build cache has been saved."
-before_install:
- - set -o errexit; source ./ci/test/00_setup_env.sh
- - set -o errexit; source ./ci/test/03_before_install.sh
-install:
- - set -o errexit; source ./ci/test/04_install.sh
-before_script:
- # Temporary workaround for https://github.com/bitcoin/bitcoin/issues/16368
- - for i in {1..4}; do echo "$(sleep 500)" ; done &
- - set -o errexit; source ./ci/test/05_before_script.sh &> "/dev/null"
-script:
- - export CONTINUE=1
- - if [ $SECONDS -gt 1200 ]; then export CONTINUE=0; fi # Likely the depends build took very long
- - if [ $TRAVIS_REPO_SLUG = "bitcoin/bitcoin" ]; then export CONTINUE=1; fi # continue on repos with extended build time (90 minutes)
- - if [ $CONTINUE = "1" ]; then set -o errexit; source ./ci/test/06_script_a.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi
- - if [[ $SECONDS -gt 50*60-$EXPECTED_TESTS_DURATION_IN_SECONDS ]]; then export CONTINUE=0; fi
- - if [ $TRAVIS_REPO_SLUG = "bitcoin/bitcoin" ]; then export CONTINUE=1; fi # continue on repos with extended build time (90 minutes)
- - if [ $CONTINUE = "1" ]; then set -o errexit; source ./ci/test/06_script_b.sh; else set +o errexit; echo "$CACHE_ERR_MSG"; false; fi
-after_script:
- - echo $TRAVIS_COMMIT_RANGE
-jobs:
- include:
-
- - stage: lint
- name: 'lint'
- env:
- cache: pip
- language: python
- python: '3.5' # Oldest supported version according to doc/dependencies.md
- install:
- - set -o errexit; source ./ci/lint/04_install.sh
- before_script:
- - set -o errexit; source ./ci/lint/05_before_script.sh
- script:
- - set -o errexit; source ./ci/lint/06_script.sh
-
- - stage: test
- name: 'ARM [GOAL: install] [buster] [unit tests, no functional tests]'
- arch: arm64 # Can disable QEMU_USER_CMD and run the tests natively without qemu
- env: >-
- FILE_ENV="./ci/test/00_setup_env_arm.sh"
- QEMU_USER_CMD=""
-
- - stage: test
- name: 'S390x [GOAL: install] [buster] [unit tests, functional tests]'
- arch: s390x # Can disable QEMU_USER_CMD and run the tests natively without qemu
- env: >-
- FILE_ENV="./ci/test/00_setup_env_s390x.sh"
- QEMU_USER_CMD=""
-
- - stage: test
- name: 'Win64 [GOAL: deploy] [unit tests, no gui, no boost::process, no functional tests]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_win64.sh"
-
- - stage: test
- name: '32-bit + dash [GOAL: install] [CentOS 7] [gui]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_i686_centos.sh"
-
- - stage: test
- name: 'x86_64 Linux [GOAL: install] [bionic] [C++17, previous releases, uses qt5 dev package and some depends packages] [unsigned char]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_native_qt5.sh"
-
- - stage: test
- name: 'x86_64 Linux [GOAL: install] [focal] [depends, sanitizers: memory (MSan)]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_native_msan.sh"
-
- - stage: test
- name: 'x86_64 Linux [GOAL: install] [focal] [no depends, only system libs, sanitizers: fuzzer,address,undefined]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_native_fuzz.sh"
-
- - stage: test
- name: 'x86_64 Linux [GOAL: install] [focal] [multiprocess]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_native_multiprocess.sh"
-
- - stage: test
- name: 'x86_64 Linux [GOAL: install] [xenial] [no wallet]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_native_nowallet.sh"
-
- - stage: test
- name: 'macOS 10.12 [GOAL: deploy] [no functional tests]'
- env: >-
- FILE_ENV="./ci/test/00_setup_env_mac.sh"
-
- - stage: test
- name: 'macOS 10.14 native [GOAL: install] [GUI] [no depends]'
- os: osx
- # Use the most recent version:
- # Xcode 11.3.1, macOS 10.14, SDK 10.15
- # https://docs.travis-ci.com/user/reference/osx/#macos-version
- osx_image: xcode11.3
- addons:
- homebrew:
- packages:
- - berkeley-db4
- - miniupnpc
- - qrencode
- - sqlite
- - ccache
- - zeromq
- env: >-
- DANGER_RUN_CI_ON_HOST=true
- CI_USE_APT_INSTALL=no
- FILE_ENV="./ci/test/00_setup_env_mac_host.sh"
diff --git a/Makefile.am b/Makefile.am
index c8af4228f3..6573f91d97 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -25,6 +25,8 @@ BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT)
BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT)
BITCOIN_TX_BIN=$(top_builddir)/src/$(BITCOIN_TX_NAME)$(EXEEXT)
BITCOIN_WALLET_BIN=$(top_builddir)/src/$(BITCOIN_WALLET_TOOL_NAME)$(EXEEXT)
+BITCOIN_NODE_BIN=$(top_builddir)/src/$(BITCOIN_MP_NODE_NAME)$(EXEEXT)
+BITCOIN_GUI_BIN=$(top_builddir)/src/$(BITCOIN_MP_GUI_NAME)$(EXEEXT)
BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win64-setup$(EXEEXT)
empty :=
@@ -33,15 +35,13 @@ space := $(empty) $(empty)
OSX_APP=Bitcoin-Qt.app
OSX_VOLNAME = $(subst $(space),-,$(PACKAGE_NAME))
OSX_DMG = $(OSX_VOLNAME).dmg
+OSX_TEMP_ISO = $(OSX_DMG:.dmg=).temp.iso
OSX_BACKGROUND_SVG=background.svg
OSX_BACKGROUND_IMAGE=background.tiff
OSX_BACKGROUND_IMAGE_DPIS=36 72
-OSX_DSSTORE_GEN=$(top_srcdir)/contrib/macdeploy/custom_dsstore.py
OSX_DEPLOY_SCRIPT=$(top_srcdir)/contrib/macdeploy/macdeployqtplus
-OSX_FANCY_PLIST=$(top_srcdir)/contrib/macdeploy/fancy.plist
OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns
OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed
-OSX_QT_TRANSLATIONS = ar,bg,ca,cs,da,de,es,fa,fi,fr,gd,gl,he,hu,it,ja,ko,lt,lv,pl,pt,ru,sk,sl,sv,uk,zh_CN,zh_TW
DIST_CONTRIB = \
$(top_srcdir)/contrib/linearize/linearize-data.py \
@@ -59,9 +59,8 @@ WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
$(top_srcdir)/share/pixmaps/nsis-wizard.bmp \
$(top_srcdir)/doc/README_windows.txt
-OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \
+OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_INSTALLER_ICONS) \
$(top_srcdir)/contrib/macdeploy/$(OSX_BACKGROUND_SVG) \
- $(OSX_DSSTORE_GEN) \
$(top_srcdir)/contrib/macdeploy/detached-sig-apply.sh \
$(top_srcdir)/contrib/macdeploy/detached-sig-create.sh
@@ -117,7 +116,7 @@ osx_volname:
if BUILD_DARWIN
$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING) $(OSX_BACKGROUND_IMAGE)
- $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 -volname $(OSX_VOLNAME)
+ $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR) -dmg
$(OSX_BACKGROUND_IMAGE).png: contrib/macdeploy/$(OSX_BACKGROUND_SVG)
sed 's/PACKAGE_NAME/$(PACKAGE_NAME)/' < "$<" | $(RSVG_CONVERT) -f png -d 36 -p 36 -o $@
@@ -137,8 +136,12 @@ $(APP_DIST_DIR)/Applications:
$(APP_DIST_EXTRAS): $(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt
-$(OSX_DMG): $(APP_DIST_EXTRAS)
- $(GENISOIMAGE) -no-cache-inodes -D -l -probe -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -apple -o $@ dist
+.INTERMEDIATE: $(OSX_TEMP_ISO)
+$(OSX_TEMP_ISO): $(APP_DIST_EXTRAS)
+ $(XORRISOFS) -D -l -V "$(OSX_VOLNAME)" -no-pad -r -dir-mode 0755 -o $@ dist
+
+$(OSX_DMG): $(OSX_TEMP_ISO)
+ $(DMG) dmg "$<" "$@"
dpi%.$(OSX_BACKGROUND_IMAGE): contrib/macdeploy/$(OSX_BACKGROUND_SVG)
sed 's/PACKAGE_NAME/$(PACKAGE_NAME)/' < "$<" | $(RSVG_CONVERT) -f png -d $* -p $* | $(IMAGEMAGICK_CONVERT) - $@
@@ -147,11 +150,8 @@ $(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE_DPIF
$(MKDIR_P) $(@D)
$(TIFFCP) -c none $(OSX_BACKGROUND_IMAGE_DPIFILES) $@
-$(APP_DIST_DIR)/.DS_Store: $(OSX_DSSTORE_GEN)
- $(PYTHON) $< "$@" "$(OSX_VOLNAME)"
-
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
- INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
+ INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) $(OSX_VOLNAME) -translations-dir=$(QT_TRANSLATION_DIR)
deploydir: $(APP_DIST_EXTRAS)
endif
@@ -179,6 +179,12 @@ $(BITCOIN_TX_BIN): FORCE
$(BITCOIN_WALLET_BIN): FORCE
$(MAKE) -C src $(@F)
+$(BITCOIN_NODE_BIN): FORCE
+ $(MAKE) -C src $(@F)
+
+$(BITCOIN_GUI_BIN): FORCE
+ $(MAKE) -C src $(@F)
+
if USE_LCOV
LCOV_FILTER_PATTERN = \
-p "/usr/local/" \
@@ -353,10 +359,13 @@ clean-local: clean-docs
test-security-check:
if TARGET_DARWIN
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_MACHO
+ $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_MACHO
endif
if TARGET_WINDOWS
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_PE
+ $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_PE
endif
if TARGET_LINUX
$(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-security-check.py TestSecurityChecks.test_ELF
+ $(AM_V_at) $(PYTHON) $(top_srcdir)/contrib/devtools/test-symbol-check.py TestSymbolChecks.test_ELF
endif
diff --git a/CODEOWNERS b/REVIEWERS
index 24a80fb35d..fa9a8f525f 100644
--- a/CODEOWNERS
+++ b/REVIEWERS
@@ -1,20 +1,15 @@
# ==============================================================================
-# Bitcoin Core CODEOWNERS
+# Bitcoin Core REVIEWERS
# ==============================================================================
-# Configuration of code ownership and review approvals for the bitcoin/bitcoin
-# repo.
+# Configuration of automated review requests for the bitcoin/bitcoin repo
+# via DrahtBot.
-# Order is important; the last matching pattern takes the most precedence.
-# More info on how this file works can be found at:
-# https://help.github.com/articles/about-codeowners/
+# Order is not important; if a modified file or directory matches a fnmatch,
+# the reviewer will be mentioned in a PR comment requesting a review.
-# This file is called CODEOWNERS because it is a magic file for GitHub to
-# automatically suggest reviewers. In this project's case, the names below
-# should be thought of as code reviewers rather than owners. Regular
-# contributors are free to add their names to specific directories or files
-# provided that they are willing to provide a review when automatically
-# assigned.
+# Regular contributors are free to add their names to specific directories or
+# files provided that they are willing to provide a review.
# Absence from this list should not be interpreted as a discouragement to
# review a pull request. Peer review is always welcome and is a critical
@@ -23,12 +18,12 @@
# Maintainers
-# @laanwj
-# @sipa
# @fanquake
# @jonasschnelli
+# @laanwj
# @marcofalke
# @meshcollider
+# @sipa
# Docs
/doc/*[a-zA-Z-].md @harding
diff --git a/build-aux/m4/bitcoin_find_bdb48.m4 b/build-aux/m4/bitcoin_find_bdb48.m4
index aa0111e5a2..5fc5b493d3 100644
--- a/build-aux/m4/bitcoin_find_bdb48.m4
+++ b/build-aux/m4/bitcoin_find_bdb48.m4
@@ -6,7 +6,9 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
AC_ARG_VAR(BDB_CFLAGS, [C compiler flags for BerkeleyDB, bypasses autodetection])
AC_ARG_VAR(BDB_LIBS, [Linker flags for BerkeleyDB, bypasses autodetection])
- if test "x$BDB_CFLAGS" = "x"; then
+ if test "x$use_bdb" = "xno"; then
+ use_bdb=no
+ elif test "x$BDB_CFLAGS" = "x"; then
AC_MSG_CHECKING([for Berkeley DB C++ headers])
BDB_CPPFLAGS=
bdbpath=X
@@ -44,25 +46,30 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
],[])
done
if test "x$bdbpath" = "xX"; then
+ use_bdb=no
AC_MSG_RESULT([no])
- AC_MSG_ERROR([libdb_cxx headers missing, ]AC_PACKAGE_NAME[ requires this library for wallet functionality (--disable-wallet to disable wallet functionality)])
+ AC_MSG_ERROR([libdb_cxx headers missing, ]AC_PACKAGE_NAME[ requires this library for BDB wallet support (--without-bdb to disable BDB wallet support)])
elif test "x$bdb48path" = "xX"; then
BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdbpath}],db_cxx)
AC_ARG_WITH([incompatible-bdb],[AS_HELP_STRING([--with-incompatible-bdb], [allow using a bdb version other than 4.8])],[
- AC_MSG_WARN([Found Berkeley DB other than 4.8; wallets opened by this build will not be portable!])
+ AC_MSG_WARN([Found Berkeley DB other than 4.8; BDB wallets opened by this build will not be portable!])
],[
- AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable wallets (--with-incompatible-bdb to ignore or --disable-wallet to disable wallet functionality)])
+ AC_MSG_ERROR([Found Berkeley DB other than 4.8, required for portable BDB wallets (--with-incompatible-bdb to ignore or --without-bdb to disable BDB wallet support)])
])
+ use_bdb=yes
else
BITCOIN_SUBDIR_TO_INCLUDE(BDB_CPPFLAGS,[${bdb48path}],db_cxx)
bdbpath="${bdb48path}"
+ use_bdb=yes
fi
else
BDB_CPPFLAGS=${BDB_CFLAGS}
fi
AC_SUBST(BDB_CPPFLAGS)
- if test "x$BDB_LIBS" = "x"; then
+ if test "x$use_bdb" = "xno"; then
+ use_bdb=no
+ elif test "x$BDB_LIBS" = "x"; then
# TODO: Ideally this could find the library version and make sure it matches the headers being used
for searchlib in db_cxx-4.8 db_cxx db4_cxx; do
AC_CHECK_LIB([$searchlib],[main],[
@@ -71,8 +78,12 @@ AC_DEFUN([BITCOIN_FIND_BDB48],[
])
done
if test "x$BDB_LIBS" = "x"; then
- AC_MSG_ERROR([libdb_cxx missing, ]AC_PACKAGE_NAME[ requires this library for wallet functionality (--disable-wallet to disable wallet functionality)])
+ AC_MSG_ERROR([libdb_cxx missing, ]AC_PACKAGE_NAME[ requires this library for BDB wallet support (--without-bdb to disable BDB wallet support)])
fi
fi
- AC_SUBST(BDB_LIBS)
+ if test "x$use_bdb" != "xno"; then
+ AC_SUBST(BDB_LIBS)
+ AC_DEFINE([USE_BDB], [1], [Define if BDB support should be compiled in])
+ use_bdb=yes
+ fi
])
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index 6c7665830b..658dfc5476 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -128,7 +128,6 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
_BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)],[-lqxcb -lxcb-static])
AC_DEFINE(QT_QPA_PLATFORM_XCB, 1, [Define this symbol if the qt platform is xcb])
elif test "x$TARGET_OS" = xdarwin; then
- AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)])
_BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa])
AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa])
elif test "x$TARGET_OS" = xandroid; then
@@ -202,7 +201,7 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[
*darwin*)
BITCOIN_QT_CHECK([
MOC_DEFS="${MOC_DEFS} -DQ_OS_MAC"
- base_frameworks="-framework Foundation -framework ApplicationServices -framework AppKit"
+ base_frameworks="-framework Foundation -framework AppKit"
AX_CHECK_LINK_FLAG([[$base_frameworks]],[QT_LIBS="$QT_LIBS $base_frameworks"],[AC_MSG_ERROR(could not find base frameworks)])
])
;;
diff --git a/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj b/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj
index 17cd31a52e..65ce1ee9da 100644
--- a/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj
+++ b/build_msvc/bitcoin-qt/bitcoin-qt.vcxproj
@@ -56,7 +56,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>$(QtReleaseLibraries);%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalOptions>/ignore:4206</AdditionalOptions>
+ <AdditionalOptions>/ignore:4206 /LTCG:OFF</AdditionalOptions>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\src;</AdditionalIncludeDirectories>
diff --git a/build_msvc/bitcoin_config.h b/build_msvc/bitcoin_config.h
index 9d0b50a0b4..53aead38b5 100644
--- a/build_msvc/bitcoin_config.h
+++ b/build_msvc/bitcoin_config.h
@@ -15,13 +15,10 @@
#define CLIENT_VERSION_IS_RELEASE false
/* Major version */
-#define CLIENT_VERSION_MAJOR 0
+#define CLIENT_VERSION_MAJOR 21
/* Minor version */
-#define CLIENT_VERSION_MINOR 20
-
-/* Build revision */
-#define CLIENT_VERSION_REVISION 99
+#define CLIENT_VERSION_MINOR 99
/* Copyright holder(s) before %s replacement */
#define COPYRIGHT_HOLDERS "The %s developers"
@@ -38,6 +35,12 @@
/* Define to 1 to enable wallet functions */
#define ENABLE_WALLET 1
+/* Define to 1 to enable BDB wallet */
+#define USE_BDB 1
+
+/* Define to 1 to enable SQLite wallet */
+#define USE_SQLITE 1
+
/* Define to 1 to enable ZMQ functions */
#define ENABLE_ZMQ 1
@@ -253,7 +256,7 @@
#define PACKAGE_NAME "Bitcoin Core"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "Bitcoin Core 0.19.99"
+#define PACKAGE_STRING "Bitcoin Core 21.99.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "bitcoin"
@@ -262,7 +265,7 @@
#define PACKAGE_URL "https://bitcoincore.org/"
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.19.99"
+#define PACKAGE_VERSION "21.99.0"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
diff --git a/build_msvc/bitcoind/bitcoind.vcxproj b/build_msvc/bitcoind/bitcoind.vcxproj
index ae24cb100e..48dfafaee0 100644
--- a/build_msvc/bitcoind/bitcoind.vcxproj
+++ b/build_msvc/bitcoind/bitcoind.vcxproj
@@ -63,6 +63,10 @@
<ReplaceInFile FilePath="$(ConfigIniOut)"
Replace="@ENABLE_WALLET_TRUE@" By=""></ReplaceInFile>
<ReplaceInFile FilePath="$(ConfigIniOut)"
+ Replace="@USE_BDB_TRUE@" By=""></ReplaceInFile>
+ <ReplaceInFile FilePath="$(ConfigIniOut)"
+ Replace="@USE_SQLITE_TRUE@" By=""></ReplaceInFile>
+ <ReplaceInFile FilePath="$(ConfigIniOut)"
Replace="@BUILD_BITCOIN_CLI_TRUE@" By=""></ReplaceInFile>
<ReplaceInFile FilePath="$(ConfigIniOut)"
Replace="@BUILD_BITCOIND_TRUE@" By=""></ReplaceInFile>
diff --git a/build_msvc/common.init.vcxproj b/build_msvc/common.init.vcxproj
index ed227519ae..9c589bccbc 100644
--- a/build_msvc/common.init.vcxproj
+++ b/build_msvc/common.init.vcxproj
@@ -4,8 +4,6 @@
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
- <VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
- <VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
<UseNativeEnvironment>true</UseNativeEnvironment>
</PropertyGroup>
@@ -16,6 +14,8 @@
<VcpkgUseStatic>true</VcpkgUseStatic>
<VcpkgAutoLink>true</VcpkgAutoLink>
<VcpkgConfiguration>$(Configuration)</VcpkgConfiguration>
+ <VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
+ <VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' and !Exists('$(WindowsSdkDir)\DesignTime\CommonConfiguration\Neutral\Windows.props')">
@@ -45,66 +45,46 @@
</ProjectConfiguration>
</ItemGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
- <LinkIncremental>true</LinkIncremental>
- <WholeProgramOptimization>false</WholeProgramOptimization>
- <UseDebugLibraries>true</UseDebugLibraries>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <LinkIncremental>false</LinkIncremental>
+ <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
+ <GenerateManifest>No</GenerateManifest>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
- <LinkIncremental>false</LinkIncremental>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <UseDebugLibraries>false</UseDebugLibraries>
+
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+ <LinkIncremental>true</LinkIncremental>
+ <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir>
<IntDir>$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
-<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
-
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <SDLCheck>true</SDLCheck>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- </ItemDefinitionGroup>
-
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <Optimization>MaxSpeed</Optimization>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <DebugInformationFormat>None</DebugInformationFormat>
</ClCompile>
<Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>false</EnableCOMDATFolding>
+ <OptimizeReferences>false</OptimizeReferences>
+ <AdditionalOptions>/LTCG:OFF</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -124,7 +104,6 @@
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>Iphlpapi.lib;ws2_32.lib;Shlwapi.lib;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Lib>
diff --git a/build_msvc/common.vcxproj b/build_msvc/common.vcxproj
index 4bbcc3767f..270c75e8a7 100644
--- a/build_msvc/common.vcxproj
+++ b/build_msvc/common.vcxproj
@@ -4,7 +4,7 @@
<Target Name="CopyBuildArtifacts" Condition="'$(ConfigurationType)' != 'StaticLibrary'">
<ItemGroup>
<BuildArtifacts Include="$(OutDir)$(TargetName)$(TargetExt)"></BuildArtifacts>
- <BuildArtifacts Include="$(OutDir)$(TargetName).pdb"></BuildArtifacts>
+ <BuildArtifacts Include="$(OutDir)$(TargetName).pdb" Condition="Exists('$(OutDir)$(TargetName).pdb')"></BuildArtifacts>
</ItemGroup>
<Copy SourceFiles="@(BuildArtifacts)" SkipUnchangedFiles="true" DestinationFolder="..\..\src\" Condition="'$(OutDir)' != ''"></Copy>
</Target>
diff --git a/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in b/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in
index 9c8279c72a..613d5c7199 100644
--- a/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in
+++ b/build_msvc/libbitcoin_wallet/libbitcoin_wallet.vcxproj.in
@@ -8,6 +8,9 @@
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<ItemGroup>
+ <ClCompile Include="..\..\src\wallet\bdb.cpp" />
+ <ClCompile Include="..\..\src\wallet\salvage.cpp" />
+ <ClCompile Include="..\..\src\wallet\sqlite.cpp" />
@SOURCE_FILES@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
diff --git a/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj b/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
index 2095c0c321..1ddd62edf2 100644
--- a/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
+++ b/build_msvc/test_bitcoin-qt/test_bitcoin-qt.vcxproj
@@ -73,7 +73,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>$(QtLibraryDir)\Qt5Test.lib;$(QtReleaseLibraries);%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalOptions>/ignore:4206</AdditionalOptions>
+ <AdditionalOptions>/ignore:4206 /LTCG:OFF</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
@@ -83,7 +83,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>$(QtDebugLibraries);%(AdditionalDependencies)</AdditionalDependencies>
- <AdditionalOptions>/ignore:4206</AdditionalOptions>
+ <AdditionalOptions>/ignore:4206</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh
index fae424051d..43d33b3f3b 100755
--- a/ci/lint/04_install.sh
+++ b/ci/lint/04_install.sh
@@ -6,14 +6,14 @@
export LC_ALL=C
-travis_retry sudo apt update && sudo apt install -y clang-format-9
-sudo update-alternatives --install /usr/bin/clang-format clang-format $(which clang-format-9 ) 100
-sudo update-alternatives --install /usr/bin/clang-format-diff clang-format-diff $(which clang-format-diff-9) 100
+${CI_RETRY_EXE} apt update && apt install -y clang-format-9 python3-pip curl git
+update-alternatives --install /usr/bin/clang-format clang-format $(which clang-format-9 ) 100
+update-alternatives --install /usr/bin/clang-format-diff clang-format-diff $(which clang-format-diff-9) 100
-travis_retry pip3 install codespell==1.17.1
-travis_retry pip3 install flake8==3.8.3
-travis_retry pip3 install yq
-travis_retry pip3 install mypy==0.781
+${CI_RETRY_EXE} pip3 install codespell==1.17.1
+${CI_RETRY_EXE} pip3 install flake8==3.8.3
+${CI_RETRY_EXE} pip3 install yq
+${CI_RETRY_EXE} pip3 install mypy==0.781
SHELLCHECK_VERSION=v0.7.1
curl -sL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar --xz -xf - --directory /tmp/
diff --git a/ci/lint/05_before_script.sh b/ci/lint/05_before_script.sh
index 2987812c8e..8e5a177b01 100755
--- a/ci/lint/05_before_script.sh
+++ b/ci/lint/05_before_script.sh
@@ -6,4 +6,4 @@
export LC_ALL=C
-git fetch --unshallow
+git fetch
diff --git a/ci/lint/06_script.sh b/ci/lint/06_script.sh
index dc0f9b923b..ba582e7bf6 100755
--- a/ci/lint/06_script.sh
+++ b/ci/lint/06_script.sh
@@ -6,14 +6,16 @@
export LC_ALL=C
-if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
- # TRAVIS_BRANCH will be present in a Travis environment. For builds triggered
+if [ -n "$CIRRUS_PR" ]; then
+ # CIRRUS_PR will be present in a Cirrus environment. For builds triggered
# by a pull request this is the name of the branch targeted by the pull request.
- # https://docs.travis-ci.com/user/environment-variables/
- COMMIT_RANGE="$TRAVIS_BRANCH..HEAD"
+ # https://cirrus-ci.org/guide/writing-tasks/#environment-variables
+ COMMIT_RANGE="$CIRRUS_BRANCH..HEAD"
test/lint/commit-script-check.sh $COMMIT_RANGE
fi
+# This only checks that the trees are pure subtrees, it is not doing a full
+# check with -r to not have to fetch all the remotes.
test/lint/git-subtree-check.sh src/crypto/ctaes
test/lint/git-subtree-check.sh src/secp256k1
test/lint/git-subtree-check.sh src/univalue
@@ -23,8 +25,8 @@ test/lint/check-doc.py
test/lint/check-rpc-mappings.py .
test/lint/lint-all.sh
-if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" ] && [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then
+if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ -n "$CIRRUS_CRON" ]; then
git log --merges --before="2 days ago" -1 --format='%H' > ./contrib/verify-commits/trusted-sha512-root-commit
- travis_retry gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys $(<contrib/verify-commits/trusted-keys) &&
+ ${CI_RETRY_EXE} gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys $(<contrib/verify-commits/trusted-keys) &&
./contrib/verify-commits/verify-commits.py --clean-merge=2;
fi
diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh
index 702e881862..72e29141a6 100755
--- a/ci/test/00_setup_env.sh
+++ b/ci/test/00_setup_env.sh
@@ -38,7 +38,7 @@ export RUN_SECURITY_TESTS=${RUN_SECURITY_TESTS:-false}
# By how much to scale the test_runner timeouts (option --timeout-factor).
# This is needed because some ci machines have slow CPU or disk, so sanitizers
# might be slow or a reindex might be waiting on disk IO.
-export TEST_RUNNER_TIMEOUT_FACTOR=${TEST_RUNNER_TIMEOUT_FACTOR:-4}
+export TEST_RUNNER_TIMEOUT_FACTOR=${TEST_RUNNER_TIMEOUT_FACTOR:-40}
export TEST_RUNNER_ENV=${TEST_RUNNER_ENV:-}
export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false}
export EXPECTED_TESTS_DURATION_IN_SECONDS=${EXPECTED_TESTS_DURATION_IN_SECONDS:-1000}
diff --git a/ci/test/00_setup_env_arm.sh b/ci/test/00_setup_env_arm.sh
index 610e55c4c3..42783197a9 100644
--- a/ci/test/00_setup_env_arm.sh
+++ b/ci/test/00_setup_env_arm.sh
@@ -25,4 +25,4 @@ export RUN_FUNCTIONAL_TESTS=false
export GOAL="install"
# -Wno-psabi is to disable ABI warnings: "note: parameter passing for argument of type ... changed in GCC 7.1"
# This could be removed once the ABI change warning does not show up by default
-export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi --enable-werror --with-boost-process"
+export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi --with-boost-process"
diff --git a/ci/test/00_setup_env_i686_centos.sh b/ci/test/00_setup_env_i686_centos.sh
index e58003ab19..1ec44a7a1a 100644
--- a/ci/test/00_setup_env_i686_centos.sh
+++ b/ci/test/00_setup_env_i686_centos.sh
@@ -7,9 +7,10 @@
export LC_ALL=C.UTF-8
export HOST=i686-pc-linux-gnu
-export CONTAINER_NAME=ci_i686_centos_7
-export DOCKER_NAME_TAG=centos:7
-export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python36-zmq which patch lbzip2 dash"
+export CONTAINER_NAME=ci_i686_centos_8
+export DOCKER_NAME_TAG=centos:8
+export DOCKER_PACKAGES="gcc-c++ glibc-devel.x86_64 libstdc++-devel.x86_64 glibc-devel.i686 libstdc++-devel.i686 ccache libtool make git python3 python3-zmq which patch lbzip2 dash rsync coreutils"
export GOAL="install"
export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-reduce-exports --with-boost-process"
export CONFIG_SHELL="/bin/dash"
+export TEST_RUNNER_ENV="LC_ALL=en_US.UTF-8"
diff --git a/ci/test/00_setup_env_mac.sh b/ci/test/00_setup_env_mac.sh
index b62f1603f4..b0de2ec0bb 100644
--- a/ci/test/00_setup_env_mac.sh
+++ b/ci/test/00_setup_env_mac.sh
@@ -7,11 +7,12 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_macos_cross
-export HOST=x86_64-apple-darwin16
-export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools"
+export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can cross-compile to macos (bionic is used in the gitian build as well)
+export HOST=x86_64-apple-darwin18
+export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools xorriso"
export XCODE_VERSION=11.3.1
export XCODE_BUILD_ID=11C505
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
export GOAL="deploy"
-export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --enable-werror --with-boost-process"
+export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --with-boost-process"
diff --git a/ci/test/00_setup_env_mac_host.sh b/ci/test/00_setup_env_mac_host.sh
index 5fb127b762..274a0d1b7c 100644
--- a/ci/test/00_setup_env_mac_host.sh
+++ b/ci/test/00_setup_env_mac_host.sh
@@ -6,17 +6,13 @@
export LC_ALL=C.UTF-8
-export HOST=x86_64-apple-darwin16
-export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can cross-compile to macos (bionic is used in the gitian build as well)
+export HOST=x86_64-apple-darwin18
export PIP_PACKAGES="zmq"
export GOAL="install"
-export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --enable-werror --with-boost-process"
+export BITCOIN_CONFIG="--with-gui --enable-reduce-exports --with-boost-process"
+export CI_OS_NAME="macos"
export NO_DEPENDS=1
export OSX_SDK=""
export CCACHE_SIZE=300M
export RUN_SECURITY_TESTS="true"
-if [ "$TRAVIS_REPO_SLUG" != "bitcoin/bitcoin" ]; then
- export RUN_FUNCTIONAL_TESTS="false"
- export EXPECTED_TESTS_DURATION_IN_SECONDS=200
-fi
diff --git a/ci/test/00_setup_env_native_msan.sh b/ci/test/00_setup_env_native_msan.sh
index b88ee2b50f..3ce50f816f 100644
--- a/ci/test/00_setup_env_native_msan.sh
+++ b/ci/test/00_setup_env_native_msan.sh
@@ -15,7 +15,7 @@ export BDB_PREFIX="${BASE_ROOT_DIR}/db4"
export CONTAINER_NAME="ci_native_msan"
export PACKAGES="clang-9 llvm-9 cmake"
-export DEP_OPTS="NO_BDB=1 NO_QT=1 CC='clang' CXX='clang++' CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' boost_cxxflags='-std=c++11 -fvisibility=hidden -fPIC ${MSAN_AND_LIBCXX_FLAGS}' zeromq_cxxflags='-std=c++11 ${MSAN_AND_LIBCXX_FLAGS}'"
+export DEP_OPTS="NO_BDB=1 NO_QT=1 CC='clang' CXX='clang++' CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' boost_cxxflags='-std=c++17 -fvisibility=hidden -fPIC ${MSAN_AND_LIBCXX_FLAGS}' zeromq_cxxflags='-std=c++17 ${MSAN_AND_LIBCXX_FLAGS}'"
export GOAL="install"
export BITCOIN_CONFIG="--enable-wallet --with-sanitizers=memory --with-asm=no --prefix=${BASE_ROOT_DIR}/depends/x86_64-pc-linux-gnu/ CC=clang CXX=clang++ CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' BDB_LIBS='-L${BDB_PREFIX}/lib -ldb_cxx-4.8' BDB_CFLAGS='-I${BDB_PREFIX}/include'"
export USE_MEMORY_SANITIZER="true"
diff --git a/ci/test/00_setup_env_native_nowallet.sh b/ci/test/00_setup_env_native_nowallet.sh
index 0a09bfe230..7ff044c020 100644
--- a/ci/test/00_setup_env_native_nowallet.sh
+++ b/ci/test/00_setup_env_native_nowallet.sh
@@ -7,8 +7,8 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_nowallet
-export DOCKER_NAME_TAG=ubuntu:16.04 # Use xenial to have one config run the tests in python3.5, see doc/dependencies.md
-export PACKAGES="python3-zmq clang-3.8 llvm-3.8" # Use clang-3.8 to test C++11 compatibility, see doc/dependencies.md
+export DOCKER_NAME_TAG=ubuntu:18.04 # Use bionic to have one config run the tests in python3.6, see doc/dependencies.md
+export PACKAGES="python3-zmq clang-5.0 llvm-5.0" # Use clang-5 to test C++17 compatibility, see doc/dependencies.md
export DEP_OPTS="NO_WALLET=1"
export GOAL="install"
-export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-3.8 CXX=clang++-3.8 --with-boost-process"
+export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CC=clang-5.0 CXX=clang++-5.0 --with-boost-process"
diff --git a/ci/test/00_setup_env_native_qt5.sh b/ci/test/00_setup_env_native_qt5.sh
index 6f2e39429c..dc6b2aecb5 100644
--- a/ci/test/00_setup_env_native_qt5.sh
+++ b/ci/test/00_setup_env_native_qt5.sh
@@ -7,7 +7,7 @@
export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_native_qt5
-export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can compile our c++17 and run our functional tests in python3
+export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic gcc-7 can compile our c++17 and run our functional tests in python3, see doc/dependencies.md
export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libdbus-1-dev libharfbuzz-dev"
export DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
export TEST_RUNNER_EXTRA="--previous-releases --coverage --extended --exclude feature_dbcrash" # Run extended tests so that coverage does not fail, but exclude the very slow dbcrash
@@ -16,4 +16,4 @@ export RUN_UNIT_TESTS_SEQUENTIAL="true"
export RUN_UNIT_TESTS="false"
export GOAL="install"
export PREVIOUS_RELEASES_TO_DOWNLOAD="v0.15.2 v0.16.3 v0.17.2 v0.18.1 v0.19.1"
-export BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-c++17 --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" --with-boost-process"
+export BITCOIN_CONFIG="--enable-zmq --with-libs=no --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CFLAGS=\"-g0 -O2 -funsigned-char\" CXXFLAGS=\"-g0 -O2 -funsigned-char\" --with-boost-process"
diff --git a/ci/test/00_setup_env_native_tsan.sh b/ci/test/00_setup_env_native_tsan.sh
index b14a46562c..182e42ee7d 100644
--- a/ci/test/00_setup_env_native_tsan.sh
+++ b/ci/test/00_setup_env_native_tsan.sh
@@ -10,6 +10,5 @@ export CONTAINER_NAME=ci_native_tsan
export DOCKER_NAME_TAG=ubuntu:20.04
export PACKAGES="clang llvm libc++abi-dev libc++-dev python3-zmq"
export DEP_OPTS="CC=clang CXX='clang++ -stdlib=libc++'"
-export TEST_RUNNER_EXTRA="--exclude feature_block" # Low memory on Travis machines, exclude feature_block.
export GOAL="install"
export BITCOIN_CONFIG="--enable-zmq --with-gui=no CPPFLAGS='-DARENA_DEBUG -DDEBUG_LOCKORDER' CXXFLAGS='-g' --with-sanitizers=thread CC=clang CXX='clang++ -stdlib=libc++' --with-boost-process"
diff --git a/ci/test/00_setup_env_s390x.sh b/ci/test/00_setup_env_s390x.sh
index fe330920d0..accbd07e22 100644
--- a/ci/test/00_setup_env_s390x.sh
+++ b/ci/test/00_setup_env_s390x.sh
@@ -20,6 +20,7 @@ fi
export CONTAINER_NAME=ci_s390x
export DOCKER_NAME_TAG="debian:buster"
export RUN_UNIT_TESTS=true
+export TEST_RUNNER_ENV="LC_ALL=C"
export RUN_FUNCTIONAL_TESTS=true
export GOAL="install"
export BITCOIN_CONFIG="--enable-reduce-exports --with-incompatible-bdb --with-boost-process"
diff --git a/ci/test/00_setup_env_win64.sh b/ci/test/00_setup_env_win64.sh
index 2b351dff6d..affaaaa1aa 100644
--- a/ci/test/00_setup_env_win64.sh
+++ b/ci/test/00_setup_env_win64.sh
@@ -9,8 +9,12 @@ export LC_ALL=C.UTF-8
export CONTAINER_NAME=ci_win64
export DOCKER_NAME_TAG=ubuntu:18.04 # Check that bionic can cross-compile to win64 (bionic is used in the gitian build as well)
export HOST=x86_64-w64-mingw32
-export PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64"
+export PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64 file"
export RUN_FUNCTIONAL_TESTS=false
export RUN_SECURITY_TESTS="true"
export GOAL="deploy"
export BITCOIN_CONFIG="--enable-reduce-exports --disable-gui-tests --without-boost-process"
+
+# Compiler for MinGW-w64 causes false -Wreturn-type warning.
+# See https://sourceforge.net/p/mingw-w64/bugs/306/
+export NO_WERROR=1
diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh
index 632bccf574..f0ed314d19 100755
--- a/ci/test/04_install.sh
+++ b/ci/test/04_install.sh
@@ -6,15 +6,12 @@
export LC_ALL=C.UTF-8
-if [[ $DOCKER_NAME_TAG == centos* ]]; then
- export LC_ALL=en_US.utf8
-fi
if [[ $QEMU_USER_CMD == qemu-s390* ]]; then
export LC_ALL=C
fi
-if [ "$TRAVIS_OS_NAME" == "osx" ]; then
- ${CI_RETRY_EXE} pip3 install $PIP_PACKAGES
+if [ "$CI_OS_NAME" == "macos" ]; then
+ IN_GETOPT_BIN="/usr/local/opt/gnu-getopt/bin/getopt" ${CI_RETRY_EXE} pip3 install --user $PIP_PACKAGES
fi
# Create folders that are mounted into the docker
@@ -26,9 +23,7 @@ export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/l
export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan:halt_on_error=1:log_path=${BASE_SCRATCH_DIR}/sanitizer-output/tsan"
export UBSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1"
env | grep -E '^(BITCOIN_CONFIG|BASE_|QEMU_|CCACHE_|LC_ALL|BOOST_TEST_RANDOM|DEBIAN_FRONTEND|CONFIG_SHELL|(ASAN|LSAN|TSAN|UBSAN)_OPTIONS|PREVIOUS_RELEASES_DIR)' | tee /tmp/env
-if [[ $HOST = *-mingw32 ]]; then
- DOCKER_ADMIN="--cap-add SYS_ADMIN"
-elif [[ $BITCOIN_CONFIG = *--with-sanitizers=*address* ]]; then # If ran with (ASan + LSan), Docker needs access to ptrace (https://github.com/google/sanitizers/issues/764)
+if [[ $BITCOIN_CONFIG = *--with-sanitizers=*address* ]]; then # If ran with (ASan + LSan), Docker needs access to ptrace (https://github.com/google/sanitizers/issues/764)
DOCKER_ADMIN="--cap-add SYS_PTRACE"
fi
@@ -62,23 +57,23 @@ if [ -n "$DPKG_ADD_ARCH" ]; then
fi
if [[ $DOCKER_NAME_TAG == centos* ]]; then
- ${CI_RETRY_EXE} DOCKER_EXEC yum -y install epel-release
- ${CI_RETRY_EXE} DOCKER_EXEC yum -y install $DOCKER_PACKAGES $PACKAGES
+ ${CI_RETRY_EXE} DOCKER_EXEC dnf -y install epel-release
+ ${CI_RETRY_EXE} DOCKER_EXEC dnf -y --allowerasing install $DOCKER_PACKAGES $PACKAGES
elif [ "$CI_USE_APT_INSTALL" != "no" ]; then
${CI_RETRY_EXE} DOCKER_EXEC apt-get update
${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES
fi
-if [ "$TRAVIS_OS_NAME" == "osx" ]; then
+if [ "$CI_OS_NAME" == "macos" ]; then
top -l 1 -s 0 | awk ' /PhysMem/ {print}'
echo "Number of CPUs: $(sysctl -n hw.logicalcpu)"
else
DOCKER_EXEC free -m -h
DOCKER_EXEC echo "Number of CPUs \(nproc\):" \$\(nproc\)
DOCKER_EXEC echo $(lscpu | grep Endian)
- DOCKER_EXEC echo "Free disk space:"
- DOCKER_EXEC df -h
fi
+DOCKER_EXEC echo "Free disk space:"
+DOCKER_EXEC df -h
if [ ! -d ${DIR_QA_ASSETS} ]; then
DOCKER_EXEC git clone --depth=1 https://github.com/bitcoin-core/qa-assets ${DIR_QA_ASSETS}
diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh
index 8ce839fc04..d7dd5d9dec 100755
--- a/ci/test/05_before_script.sh
+++ b/ci/test/05_before_script.sh
@@ -7,7 +7,7 @@
export LC_ALL=C.UTF-8
# Make sure default datadir does not exist and is never read by creating a dummy file
-if [ "$TRAVIS_OS_NAME" == "osx" ]; then
+if [ "$CI_OS_NAME" == "macos" ]; then
echo > $HOME/Library/Application\ Support/Bitcoin
else
DOCKER_EXEC echo \> \$HOME/.bitcoin
@@ -40,7 +40,7 @@ if [ -z "$NO_DEPENDS" ]; then
# CentOS has problems building the depends if the config shell is not explicitly set
# (i.e. for libevent a Makefile with an empty SHELL variable is generated, leading to
# an error as the first command is executed)
- SHELL_OPTS="CONFIG_SHELL=/bin/bash"
+ SHELL_OPTS="LC_ALL=en_US.UTF-8 CONFIG_SHELL=/bin/bash"
else
SHELL_OPTS="CONFIG_SHELL="
fi
diff --git a/ci/test/06_script_a.sh b/ci/test/06_script_a.sh
index 17d765b862..d99068cb10 100755
--- a/ci/test/06_script_a.sh
+++ b/ci/test/06_script_a.sh
@@ -6,7 +6,10 @@
export LC_ALL=C.UTF-8
-BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
+BITCOIN_CONFIG_ALL="--enable-suppress-external-warnings --disable-dependency-tracking --prefix=$DEPENDS_DIR/$HOST --bindir=$BASE_OUTDIR/bin --libdir=$BASE_OUTDIR/lib"
+if [ -z "$NO_WERROR" ]; then
+ BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} --enable-werror"
+fi
DOCKER_EXEC "ccache --zero-stats --max-size=$CCACHE_SIZE"
BEGIN_FOLD autogen
diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh
index 607a2820dd..7aea21f257 100755
--- a/ci/test/06_script_b.sh
+++ b/ci/test/06_script_b.sh
@@ -6,6 +6,15 @@
export LC_ALL=C.UTF-8
+if [[ $HOST = *-mingw32 ]]; then
+ BEGIN_FOLD wrap-wine
+ # Generate all binaries, so that they can be wrapped
+ DOCKER_EXEC make $MAKEJOBS -C src/secp256k1 VERBOSE=1
+ DOCKER_EXEC make $MAKEJOBS -C src/univalue VERBOSE=1
+ DOCKER_EXEC "${BASE_ROOT_DIR}/ci/test/wrap-wine.sh"
+ END_FOLD
+fi
+
if [ -n "$QEMU_USER_CMD" ]; then
BEGIN_FOLD wrap-qemu
# Generate all binaries, so that they can be wrapped
@@ -23,13 +32,13 @@ fi
if [ "$RUN_UNIT_TESTS" = "true" ]; then
BEGIN_FOLD unit-tests
- DOCKER_EXEC DIR_UNIT_TEST_DATA=${DIR_UNIT_TEST_DATA} LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib make $MAKEJOBS check VERBOSE=1
+ DOCKER_EXEC ${TEST_RUNNER_ENV} DIR_UNIT_TEST_DATA=${DIR_UNIT_TEST_DATA} LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib make $MAKEJOBS check VERBOSE=1
END_FOLD
fi
if [ "$RUN_UNIT_TESTS_SEQUENTIAL" = "true" ]; then
BEGIN_FOLD unit-tests-seq
- DOCKER_EXEC DIR_UNIT_TEST_DATA=${DIR_UNIT_TEST_DATA} LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib "${BASE_BUILD_DIR}/bitcoin-*/src/test/test_bitcoin*" --catch_system_errors=no -l test_suite
+ DOCKER_EXEC ${TEST_RUNNER_ENV} DIR_UNIT_TEST_DATA=${DIR_UNIT_TEST_DATA} LD_LIBRARY_PATH=$DEPENDS_DIR/$HOST/lib "${BASE_BUILD_DIR}/bitcoin-*/src/test/test_bitcoin*" --catch_system_errors=no -l test_suite
END_FOLD
fi
diff --git a/ci/test/wrap-wine.sh b/ci/test/wrap-wine.sh
new file mode 100755
index 0000000000..58a8983e6e
--- /dev/null
+++ b/ci/test/wrap-wine.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+export LC_ALL=C.UTF-8
+
+for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/univalue/{no_nul,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
+ echo "Wrap $b ..."
+ mv "$b" "${b}_orig"
+ echo '#!/usr/bin/env bash' > "$b"
+ echo "wine64 \"${b}_orig\" \"\$@\"" >> "$b"
+ chmod +x "$b"
+ fi
+ done
+done
diff --git a/configure.ac b/configure.ac
index ab40991ce4..ef2f31e582 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,14 +1,13 @@
AC_PREREQ([2.69])
-define(_CLIENT_VERSION_MAJOR, 0)
-define(_CLIENT_VERSION_MINOR, 20)
-define(_CLIENT_VERSION_REVISION, 99)
+define(_CLIENT_VERSION_MAJOR, 21)
+define(_CLIENT_VERSION_MINOR, 99)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 0)
define(_CLIENT_VERSION_IS_RELEASE, false)
define(_COPYRIGHT_YEAR, 2020)
define(_COPYRIGHT_HOLDERS,[The %s developers])
define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin Core]])
-AC_INIT([Bitcoin Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_REVISION, m4_if(_CLIENT_VERSION_BUILD, [0], [], _CLIENT_VERSION_BUILD))m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/])
+AC_INIT([Bitcoin Core],m4_join([.], _CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MINOR, _CLIENT_VERSION_BUILD)m4_if(_CLIENT_VERSION_RC, [0], [], [rc]_CLIENT_VERSION_RC),[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/])
AC_CONFIG_SRCDIR([src/validation.cpp])
AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
AC_CONFIG_AUX_DIR([build-aux])
@@ -25,6 +24,9 @@ BITCOIN_GUI_NAME=bitcoin-qt
BITCOIN_CLI_NAME=bitcoin-cli
BITCOIN_TX_NAME=bitcoin-tx
BITCOIN_WALLET_TOOL_NAME=bitcoin-wallet
+dnl Multi Process
+BITCOIN_MP_NODE_NAME=bitcoin-node
+BITCOIN_MP_GUI_NAME=bitcoin-gui
dnl Unless the user specified ARFLAGS, force it to be cr
AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to <cr> if not set])
@@ -68,18 +70,8 @@ case $host in
;;
esac
-AC_ARG_ENABLE([c++17],
- [AS_HELP_STRING([--enable-c++17],
- [enable compilation in c++17 mode (disabled by default)])],
- [use_cxx17=$enableval],
- [use_cxx17=no])
-
-dnl Require C++11 or C++17 compiler (no GNU extensions)
-if test "x$use_cxx17" = xyes -o "x$enable_fuzz" = xyes ; then
- AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
-else
- AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
-fi
+dnl Require C++17 compiler (no GNU extensions)
+AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
dnl Check if -latomic is required for <std::atomic>
CHECK_ATOMIC
@@ -107,8 +99,8 @@ AC_PATH_TOOL(STRIP, strip)
AC_PATH_TOOL(GCOV, gcov)
AC_PATH_TOOL(LLVM_COV, llvm-cov)
AC_PATH_PROG(LCOV, lcov)
-dnl Python 3.5 is specified in .python-version and should be used if available, see doc/dependencies.md
-AC_PATH_PROGS([PYTHON], [python3.5 python3.6 python3.7 python3.8 python3 python])
+dnl Python 3.6 is specified in .python-version and should be used if available, see doc/dependencies.md
+AC_PATH_PROGS([PYTHON], [python3.6 python3.7 python3.8 python3.9 python3 python])
AC_PATH_PROG(GENHTML, genhtml)
AC_PATH_PROG([GIT], [git])
AC_PATH_PROG(CCACHE,ccache)
@@ -126,7 +118,19 @@ AC_ARG_ENABLE([wallet],
[AS_HELP_STRING([--disable-wallet],
[disable wallet (enabled by default)])],
[enable_wallet=$enableval],
- [enable_wallet=yes])
+ [enable_wallet=auto])
+
+AC_ARG_WITH([sqlite],
+ [AS_HELP_STRING([--with-sqlite=yes|no|auto],
+ [enable sqlite wallet support (default: auto, i.e., enabled if wallet is enabled and sqlite is found)])],
+ [use_sqlite=$withval],
+ [use_sqlite=auto])
+
+AC_ARG_WITH([bdb],
+ [AS_HELP_STRING([--without-bdb],
+ [disable bdb wallet support (default is enabled if wallet is enabled)])],
+ [use_bdb=$withval],
+ [use_bdb=auto])
AC_ARG_WITH([miniupnpc],
[AS_HELP_STRING([--with-miniupnpc],
@@ -166,6 +170,12 @@ AC_ARG_ENABLE([fuzz],
[enable_fuzz=$enableval],
[enable_fuzz=no])
+AC_ARG_ENABLE([danger_fuzz_link_all],
+ AS_HELP_STRING([--enable-danger-fuzz-link-all],
+ [Danger! Modifies source code. Needs git and gnu sed installed. Link each fuzz target (default no).]),
+ [enable_danger_fuzz_link_all=$enableval],
+ [enable_danger_fuzz_link_all=no])
+
AC_ARG_WITH([qrencode],
[AS_HELP_STRING([--with-qrencode],
[enable QR code support (default is yes if qt is enabled and libqrencode is found)])],
@@ -347,6 +357,7 @@ if test "x$enable_debug" = xyes; then
AX_CHECK_PREPROC_FLAG([-DDEBUG],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_PREPROC_FLAG([-DDEBUG_LOCKORDER],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG_LOCKORDER"]],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"]],,[[$CXXFLAG_WERROR]])
AX_CHECK_COMPILE_FLAG([-ftrapv],[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -ftrapv"],,[[$CXXFLAG_WERROR]])
fi
@@ -640,16 +651,19 @@ 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).
- bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null)
- qt5_prefix=$($BREW --prefix qt5 2>/dev/null)
- if test x$bdb_prefix != x && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x"; then
+ if test "x$use_bdb" != xno && $BREW list --versions berkeley-db4 >/dev/null && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x"; then
+ bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null)
dnl This must precede the call to BITCOIN_FIND_BDB48 below.
BDB_CFLAGS="-I$bdb_prefix/include"
BDB_LIBS="-L$bdb_prefix/lib -ldb_cxx-4.8"
fi
- if test x$qt5_prefix != x; then
- PKG_CONFIG_PATH="$qt5_prefix/lib/pkgconfig:$PKG_CONFIG_PATH"
- export PKG_CONFIG_PATH
+
+ if test "x$use_sqlite" != xno && $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 qt5 >/dev/null; then
+ export PKG_CONFIG_PATH="$($BREW --prefix qt5 2>/dev/null)/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
fi
else
@@ -661,7 +675,8 @@ case $host in
AC_PATH_TOOL([DSYMUTIL], [dsymutil], dsymutil)
AC_PATH_TOOL([INSTALLNAMETOOL], [install_name_tool], install_name_tool)
AC_PATH_TOOL([OTOOL], [otool], otool)
- AC_PATH_PROGS([GENISOIMAGE], [genisoimage mkisofs],genisoimage)
+ AC_PATH_PROGS([XORRISOFS], [xorrisofs], xorrisofs)
+ AC_PATH_PROGS([DMG], [dmg], dmg)
AC_PATH_PROGS([RSVG_CONVERT], [rsvg-convert rsvg],rsvg-convert)
AC_PATH_PROGS([IMAGEMAGICK_CONVERT], [convert],convert)
AC_PATH_PROGS([TIFFCP], [tiffcp],tiffcp)
@@ -1108,18 +1123,20 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
]], [[
getauxval(AT_HWCAP);
]])],
- [ AC_MSG_RESULT(yes); HAVE_STRONG_GETAUXVAL=1 ],
+ [ AC_MSG_RESULT(yes); HAVE_STRONG_GETAUXVAL=1; AC_DEFINE(HAVE_STRONG_GETAUXVAL, 1, [Define this symbol to build code that uses getauxval)]) ],
[ AC_MSG_RESULT(no); HAVE_STRONG_GETAUXVAL=0 ]
)
AC_MSG_CHECKING(for weak getauxval support in the compiler)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #ifdef __linux__
unsigned long getauxval(unsigned long type) __attribute__((weak));
#define AT_HWCAP 16
+ #endif
]], [[
getauxval(AT_HWCAP);
]])],
- [ AC_MSG_RESULT(yes); HAVE_WEAK_GETAUXVAL=1 ],
+ [ AC_MSG_RESULT(yes); HAVE_WEAK_GETAUXVAL=1; AC_DEFINE(HAVE_WEAK_GETAUXVAL, 1, [Define this symbol to build code that uses getauxval (weak linking)]) ],
[ AC_MSG_RESULT(no); HAVE_WEAK_GETAUXVAL=0 ]
)
@@ -1188,6 +1205,8 @@ if test "x$enable_fuzz" = "xyes"; then
use_upnp=no
use_zmq=no
+ AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"]],,[[$CXXFLAG_WERROR]])
+
AC_MSG_CHECKING([whether main function is needed])
AX_CHECK_LINK_FLAG(
[[-fsanitize=$use_sanitizers]],
@@ -1224,7 +1243,32 @@ if test x$enable_wallet != xno; then
fi
dnl Check for sqlite3
- PKG_CHECK_MODULES([SQLITE], [sqlite3 >= 3.7.17], , [AC_MSG_ERROR([sqlite3 not found.])])
+ if test "x$use_sqlite" != "xno"; then
+ PKG_CHECK_MODULES([SQLITE], [sqlite3 >= 3.7.17], [have_sqlite=yes], [have_sqlite=no])
+ fi
+ AC_MSG_CHECKING([whether to build wallet with support for sqlite])
+ if test "x$use_sqlite" = "xno"; then
+ use_sqlite=no
+ elif test "x$have_sqlite" = "xno"; then
+ if test "x$use_sqlite" = "xyes"; then
+ AC_MSG_ERROR([sqlite support requested but cannot be built. Use --without-sqlite])
+ fi
+ use_sqlite=no
+ else
+ if test x$use_sqlite != xno; then
+ AC_DEFINE([USE_SQLITE],[1],[Define if sqlite support should be compiled in])
+ use_sqlite=yes
+ fi
+ fi
+ AC_MSG_RESULT([$use_sqlite])
+
+ dnl Disable wallet if both --without-bdb and --without-sqlite
+ if test "x$use_bdb$use_sqlite" = "xnono"; then
+ if test "x$enable_wallet" = "xyes"; then
+ AC_MSG_ERROR([wallet functionality requested but no BDB or SQLite support available.])
+ fi
+ enable_wallet=no
+ fi
fi
dnl Check for libminiupnpc (optional)
@@ -1480,6 +1524,7 @@ AC_MSG_CHECKING([if wallet should be enabled])
if test x$enable_wallet != xno; then
AC_MSG_RESULT(yes)
AC_DEFINE_UNQUOTED([ENABLE_WALLET],[1],[Define to 1 to enable wallet functions])
+ enable_wallet=yes
else
AC_MSG_RESULT(no)
@@ -1555,7 +1600,11 @@ AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
AC_MSG_CHECKING([whether to build test_bitcoin])
if test x$use_tests = xyes; then
- AC_MSG_RESULT([yes])
+ if test "x$enable_fuzz" = "xyes"; then
+ AC_MSG_RESULT([no, because fuzzing is enabled])
+ else
+ AC_MSG_RESULT([yes])
+ fi
BUILD_TEST="yes"
else
AC_MSG_RESULT([no])
@@ -1578,8 +1627,11 @@ AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin])
AM_CONDITIONAL([TARGET_LINUX], [test x$TARGET_OS = xlinux])
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
+AM_CONDITIONAL([USE_SQLITE], [test "x$use_sqlite" = "xyes"])
+AM_CONDITIONAL([USE_BDB], [test "x$use_bdb" = "xyes"])
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes])
+AM_CONDITIONAL([ENABLE_FUZZ_LINK_ALL],[test x$enable_danger_fuzz_link_all = xyes])
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes])
@@ -1598,7 +1650,6 @@ AM_CONDITIONAL([WORDS_BIGENDIAN],[test x$ac_cv_c_bigendian = xyes])
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
-AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision])
AC_DEFINE(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD, [Version Build])
AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is release])
AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Copyright year])
@@ -1608,7 +1659,6 @@ define(_COPYRIGHT_HOLDERS_FINAL, [patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT
AC_DEFINE(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL", [Copyright holder(s)])
AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR)
AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR)
-AC_SUBST(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION)
AC_SUBST(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD)
AC_SUBST(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE)
AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR)
@@ -1620,6 +1670,8 @@ AC_SUBST(BITCOIN_GUI_NAME)
AC_SUBST(BITCOIN_CLI_NAME)
AC_SUBST(BITCOIN_TX_NAME)
AC_SUBST(BITCOIN_WALLET_TOOL_NAME)
+AC_SUBST(BITCOIN_MP_NODE_NAME)
+AC_SUBST(BITCOIN_MP_GUI_NAME)
AC_SUBST(RELDFLAGS)
AC_SUBST(DEBUG_CPPFLAGS)
@@ -1643,6 +1695,8 @@ AC_SUBST(AVX2_CXXFLAGS)
AC_SUBST(SHANI_CXXFLAGS)
AC_SUBST(ARM_CRC_CXXFLAGS)
AC_SUBST(LIBTOOL_APP_LDFLAGS)
+AC_SUBST(USE_SQLITE)
+AC_SUBST(USE_BDB)
AC_SUBST(USE_UPNP)
AC_SUBST(USE_QRCODE)
AC_SUBST(BOOST_LIBS)
@@ -1666,7 +1720,9 @@ AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt
AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh])
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])])
AC_CONFIG_LINKS([contrib/devtools/security-check.py:contrib/devtools/security-check.py])
+AC_CONFIG_LINKS([contrib/devtools/symbol-check.py:contrib/devtools/symbol-check.py])
AC_CONFIG_LINKS([contrib/devtools/test-security-check.py:contrib/devtools/test-security-check.py])
+AC_CONFIG_LINKS([contrib/devtools/test-symbol-check.py:contrib/devtools/test-symbol-check.py])
AC_CONFIG_LINKS([contrib/filter-lcov.py:contrib/filter-lcov.py])
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])
@@ -1718,13 +1774,19 @@ echo "Options used to compile and link:"
echo " boost process = $ax_cv_boost_process"
echo " multiprocess = $build_multiprocess"
echo " with wallet = $enable_wallet"
+if test "x$enable_wallet" != "xno"; then
+ echo " with sqlite = $use_sqlite"
+ echo " with bdb = $use_bdb"
+fi
echo " with gui / qt = $bitcoin_enable_qt"
if test x$bitcoin_enable_qt != xno; then
echo " with qr = $use_qr"
fi
echo " with zmq = $use_zmq"
-echo " with test = $use_tests"
-if test x$use_tests != xno; then
+if test x$enable_fuzz == xno; then
+ echo " with test = $use_tests"
+else
+ echo " with test = not building test_bitcoin because fuzzing is enabled"
echo " with fuzz = $enable_fuzz"
fi
echo " with bench = $use_bench"
diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh
index aa65953d83..3fdcda4fd4 100755
--- a/contrib/devtools/gen-manpages.sh
+++ b/contrib/devtools/gen-manpages.sh
@@ -18,6 +18,22 @@ BITCOINQT=${BITCOINQT:-$BINDIR/qt/bitcoin-qt}
[ ! -x $BITCOIND ] && echo "$BITCOIND not found or not executable." && exit 1
+# Don't allow man pages to be generated for binaries built from a dirty tree
+DIRTY=""
+for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $WALLET_TOOL $BITCOINQT; do
+ VERSION_OUTPUT=$($cmd --version)
+ if [[ $VERSION_OUTPUT == *"dirty"* ]]; then
+ DIRTY="${DIRTY}${cmd}\n"
+ fi
+done
+if [ -n "$DIRTY" ]
+then
+ echo -e "WARNING: the following binaries were built from a dirty tree:\n"
+ echo -e $DIRTY
+ echo "man pages generated from dirty binaries should NOT be committed."
+ echo "To properly generate man pages, please commit your changes to the above binaries, rebuild them, then run this script again."
+fi
+
# The autodetected version git tag can screw up manpage output a little bit
read -r -a BTCVER <<< "$($BITCOINCLI --version | head -n1 | awk -F'[ -]' '{ print $6, $7 }')"
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
index dc74de9198..02615edb54 100755
--- a/contrib/devtools/security-check.py
+++ b/contrib/devtools/security-check.py
@@ -62,7 +62,7 @@ def get_ELF_program_headers(executable):
splitline = [x.strip() for x in line.split()]
flags = splitline[ofs_flags]
# check for 'R', ' E'
- if splitline[ofs_flags + 1] is 'E':
+ if splitline[ofs_flags + 1] == 'E':
flags += ' E'
headers.append((typ, flags, []))
count += 1
diff --git a/contrib/devtools/test-symbol-check.py b/contrib/devtools/test-symbol-check.py
new file mode 100755
index 0000000000..18ed7d61e0
--- /dev/null
+++ b/contrib/devtools/test-symbol-check.py
@@ -0,0 +1,162 @@
+#!/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 script for symbol-check.py
+'''
+import subprocess
+import unittest
+
+def call_symbol_check(cc, source, executable, options):
+ subprocess.run([cc,source,'-o',executable] + options, check=True)
+ p = subprocess.run(['./contrib/devtools/symbol-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
+ return (p.returncode, p.stdout.rstrip())
+
+def get_machine(cc):
+ p = subprocess.run([cc,'-dumpmachine'], stdout=subprocess.PIPE, universal_newlines=True)
+ return p.stdout.rstrip()
+
+class TestSymbolChecks(unittest.TestCase):
+ def test_ELF(self):
+ source = 'test1.c'
+ executable = 'test1'
+ cc = 'gcc'
+
+ # there's no way to do this test for RISC-V at the moment; bionic's libc is 2.27
+ # and we allow all symbols from 2.27.
+ if 'riscv' in get_machine(cc):
+ self.skipTest("test not available for RISC-V")
+
+ # memfd_create was introduced in GLIBC 2.27, so is newer than the upper limit of
+ # all but RISC-V but still available on bionic
+ with open(source, 'w', encoding="utf8") as f:
+ f.write('''
+ #define _GNU_SOURCE
+ #include <sys/mman.h>
+
+ int memfd_create(const char *name, unsigned int flags);
+
+ int main()
+ {
+ memfd_create("test", 0);
+ return 0;
+ }
+ ''')
+
+ self.assertEqual(call_symbol_check(cc, source, executable, []),
+ (1, executable + ': symbol memfd_create from unsupported version GLIBC_2.27\n' +
+ executable + ': failed IMPORTED_SYMBOLS'))
+
+ # -lutil is part of the libc6 package so a safe bet that it's installed
+ # it's also out of context enough that it's unlikely to ever become a real dependency
+ source = 'test2.c'
+ executable = 'test2'
+ with open(source, 'w', encoding="utf8") as f:
+ f.write('''
+ #include <utmp.h>
+
+ int main()
+ {
+ login(0);
+ return 0;
+ }
+ ''')
+
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-lutil']),
+ (1, executable + ': NEEDED library libutil.so.1 is not allowed\n' +
+ executable + ': failed LIBRARY_DEPENDENCIES'))
+
+ # finally, check a conforming file that simply uses a math function
+ source = 'test3.c'
+ executable = 'test3'
+ with open(source, 'w', encoding="utf8") as f:
+ f.write('''
+ #include <math.h>
+
+ int main()
+ {
+ return (int)pow(2.0, 4.0);
+ }
+ ''')
+
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-lm']),
+ (0, ''))
+
+ def test_MACHO(self):
+ source = 'test1.c'
+ executable = 'test1'
+ cc = 'clang'
+
+ with open(source, 'w', encoding="utf8") as f:
+ f.write('''
+ #include <expat.h>
+
+ int main()
+ {
+ XML_ExpatVersion();
+ return 0;
+ }
+
+ ''')
+
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-lexpat']),
+ (1, 'libexpat.1.dylib is not in ALLOWED_LIBRARIES!\n' +
+ executable + ': failed DYNAMIC_LIBRARIES'))
+
+ source = 'test2.c'
+ executable = 'test2'
+ with open(source, 'w', encoding="utf8") as f:
+ f.write('''
+ #include <CoreGraphics/CoreGraphics.h>
+
+ int main()
+ {
+ CGMainDisplayID();
+ return 0;
+ }
+ ''')
+
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-framework', 'CoreGraphics']),
+ (0, ''))
+
+ def test_PE(self):
+ source = 'test1.c'
+ executable = 'test1.exe'
+ cc = 'x86_64-w64-mingw32-gcc'
+
+ with open(source, 'w', encoding="utf8") as f:
+ f.write('''
+ #include <pdh.h>
+
+ int main()
+ {
+ PdhConnectMachineA(NULL);
+ return 0;
+ }
+ ''')
+
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-lpdh']),
+ (1, 'pdh.dll is not in ALLOWED_LIBRARIES!\n' +
+ executable + ': failed DYNAMIC_LIBRARIES'))
+
+ source = 'test2.c'
+ executable = 'test2.exe'
+ with open(source, 'w', encoding="utf8") as f:
+ f.write('''
+ #include <windows.h>
+
+ int main()
+ {
+ CoFreeUnusedLibrariesEx(0,0);
+ return 0;
+ }
+ ''')
+
+ self.assertEqual(call_symbol_check(cc, source, executable, ['-lole32']),
+ (0, ''))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 65f9a2e5c9..0e2c5be0fa 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-linux-0.21"
+name: "bitcoin-core-linux-22"
enable_cache: true
distro: "ubuntu"
suites:
@@ -112,7 +112,7 @@ script: |
# Create the source tarball
mkdir -p "$(dirname "$GIT_ARCHIVE")"
- git archive --output="$GIT_ARCHIVE" HEAD
+ git archive --prefix="${DISTNAME}/" --output="$GIT_ARCHIVE" HEAD
ORIGPATH="$PATH"
# Extract the git archive into a dir for each host and build
@@ -129,7 +129,7 @@ script: |
cd distsrc-${i}
INSTALLPATH="${PWD}/installed/${DISTNAME}"
mkdir -p ${INSTALLPATH}
- tar -xf $GIT_ARCHIVE
+ tar --strip-components=1 -xf "${GIT_ARCHIVE}"
./autogen.sh
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}"
diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml
index a4f3219c22..2330ff7736 100644
--- a/contrib/gitian-descriptors/gitian-osx-signer.yml
+++ b/contrib/gitian-descriptors/gitian-osx-signer.yml
@@ -7,6 +7,7 @@ architectures:
- "amd64"
packages:
- "faketime"
+- "xorriso"
remotes:
- "url": "https://github.com/bitcoin-core/bitcoin-detached-sigs.git"
"dir": "signature"
@@ -18,7 +19,7 @@ script: |
WRAP_DIR=$HOME/wrapped
mkdir -p ${WRAP_DIR}
export PATH="$PWD":$PATH
- FAKETIME_PROGS="dmg genisoimage"
+ FAKETIME_PROGS="dmg xorrisofs"
# Create global faketime wrappers
for prog in ${FAKETIME_PROGS}; do
@@ -36,5 +37,5 @@ script: |
tar -xf ${UNSIGNED}
OSX_VOLNAME="$(cat osx_volname)"
./detached-sig-apply.sh ${UNSIGNED} signature/osx
- ${WRAP_DIR}/genisoimage -no-cache-inodes -D -l -probe -V "${OSX_VOLNAME}" -no-pad -r -dir-mode 0755 -apple -o uncompressed.dmg signed-app
+ ${WRAP_DIR}/xorrisofs -D -l -V "${OSX_VOLNAME}" -no-pad -r -dir-mode 0755 -o uncompressed.dmg signed-app
${WRAP_DIR}/dmg dmg uncompressed.dmg ${OUTDIR}/${SIGNED}
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index e0aaafc15a..9a7dd13c9c 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-osx-0.21"
+name: "bitcoin-core-osx-22"
enable_cache: true
distro: "ubuntu"
suites:
@@ -28,6 +28,7 @@ packages:
- "python3-dev"
- "python3-setuptools"
- "fonts-tuffy"
+- "xorriso"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
"dir": "bitcoin"
@@ -37,10 +38,10 @@ script: |
set -e -o pipefail
WRAP_DIR=$HOME/wrapped
- HOSTS="x86_64-apple-darwin16"
- CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage"
+ HOSTS="x86_64-apple-darwin18"
+ CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests XORRISOFS=${WRAP_DIR}/xorrisofs DMG=${WRAP_DIR}/dmg"
FAKETIME_HOST_PROGS=""
- FAKETIME_PROGS="ar ranlib date dmg genisoimage"
+ FAKETIME_PROGS="ar ranlib date dmg xorrisofs"
export QT_RCC_TEST=1
export QT_RCC_SOURCE_DATE_OVERRIDE=1
@@ -111,7 +112,7 @@ script: |
# Create the source tarball
mkdir -p "$(dirname "$GIT_ARCHIVE")"
- git archive --output="$GIT_ARCHIVE" HEAD
+ git archive --prefix="${DISTNAME}/" --output="$GIT_ARCHIVE" HEAD
ORIGPATH="$PATH"
# Extract the git archive into a dir for each host and build
@@ -121,7 +122,7 @@ script: |
cd distsrc-${i}
INSTALLPATH="${PWD}/installed/${DISTNAME}"
mkdir -p ${INSTALLPATH}
- tar -xf $GIT_ARCHIVE
+ tar --strip-components=1 -xf "${GIT_ARCHIVE}"
./autogen.sh
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS}
@@ -132,12 +133,11 @@ script: |
make osx_volname
make deploydir
- OSX_VOLNAME="$(cat osx_volname)"
mkdir -p unsigned-app-${i}
cp osx_volname unsigned-app-${i}/
cp contrib/macdeploy/detached-sig-apply.sh unsigned-app-${i}
cp contrib/macdeploy/detached-sig-create.sh unsigned-app-${i}
- cp ${BASEPREFIX}/${i}/native/bin/dmg ${BASEPREFIX}/${i}/native/bin/genisoimage unsigned-app-${i}
+ cp ${BASEPREFIX}/${i}/native/bin/dmg unsigned-app-${i}
cp ${BASEPREFIX}/${i}/native/bin/${i}-codesign_allocate unsigned-app-${i}/codesign_allocate
cp ${BASEPREFIX}/${i}/native/bin/${i}-pagestuff unsigned-app-${i}/pagestuff
mv dist unsigned-app-${i}
@@ -145,8 +145,7 @@ script: |
find . | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-osx-unsigned.tar.gz
popd
- make deploy
- ${WRAP_DIR}/dmg dmg "${OSX_VOLNAME}.dmg" ${OUTDIR}/${DISTNAME}-osx-unsigned.dmg
+ make deploy OSX_DMG="${OUTDIR}/${DISTNAME}-osx-unsigned.dmg"
cd installed
find . -name "lib*.la" -delete
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index 5f671b95ce..fc79745e69 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -1,5 +1,5 @@
---
-name: "bitcoin-core-win-0.21"
+name: "bitcoin-core-win-22"
enable_cache: true
distro: "ubuntu"
suites:
@@ -116,7 +116,7 @@ script: |
# Create the source tarball
mkdir -p "$(dirname "$GIT_ARCHIVE")"
- git archive --output="$GIT_ARCHIVE" HEAD
+ git archive --prefix="${DISTNAME}/" --output="$GIT_ARCHIVE" HEAD
ORIGPATH="$PATH"
# Extract the git archive into a dir for each host and build
@@ -126,7 +126,7 @@ script: |
cd distsrc-${i}
INSTALLPATH="${PWD}/installed/${DISTNAME}"
mkdir -p ${INSTALLPATH}
- tar -xf $GIT_ARCHIVE
+ tar --strip-components=1 -xf "${GIT_ARCHIVE}"
./autogen.sh
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}"
diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh
index 5be3baeefa..d658c4f6a6 100644
--- a/contrib/guix/libexec/build.sh
+++ b/contrib/guix/libexec/build.sh
@@ -158,7 +158,7 @@ GIT_ARCHIVE="${OUTDIR}/src/${DISTNAME}.tar.gz"
# Create the source tarball if not already there
if [ ! -e "$GIT_ARCHIVE" ]; then
mkdir -p "$(dirname "$GIT_ARCHIVE")"
- git archive --output="$GIT_ARCHIVE" HEAD
+ git archive --prefix="${DISTNAME}/" --output="$GIT_ARCHIVE" HEAD
fi
###########################
@@ -193,7 +193,7 @@ export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
cd "$DISTSRC"
# Extract the source tarball
- tar -xf "${GIT_ARCHIVE}"
+ tar --strip-components=1 -xf "${GIT_ARCHIVE}"
./autogen.sh
diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md
index fe677e3a1f..2d9a4a2153 100644
--- a/contrib/macdeploy/README.md
+++ b/contrib/macdeploy/README.md
@@ -6,11 +6,7 @@ The `macdeployqtplus` script should not be run manually. Instead, after building
make deploy
```
-During the deployment process, the disk image window will pop up briefly
-when the fancy settings are applied. This is normal, please do not interfere,
-the process will unmount the DMG and cleanup before finishing.
-
-When complete, it will have produced `Bitcoin-Qt.dmg`.
+When complete, it will have produced `Bitcoin-Core.dmg`.
## SDK Extraction
@@ -96,22 +92,18 @@ created using these tools. The build process has been designed to avoid includin
SDK's files in Gitian's outputs. All interim tarballs are fully deterministic and may be freely
redistributed.
-`genisoimage` is used to create the initial DMG. It is not deterministic as-is, so it has been
-patched. A system `genisoimage` will work fine, but it will not be deterministic because
-the file-order will change between invocations. The patch can be seen here: [cdrkit-deterministic.patch](https://github.com/bitcoin/bitcoin/blob/master/depends/patches/native_cdrkit/cdrkit-deterministic.patch).
-No effort was made to fix this cleanly, so it likely leaks memory badly, however it's only used for
-a single invocation, so that's no real concern.
+[`xorrisofs`](https://www.gnu.org/software/xorriso/) is used to create the DMG.
-`genisoimage` cannot compress DMGs, so afterwards, the DMG tool from the
-`libdmg-hfsplus` project is used to compress it. There are several bugs in this tool and its
-maintainer has seemingly abandoned the project.
+`xorrisofs` cannot compress DMGs, so afterwards, the DMG tool from the
+`libdmg-hfsplus` project is used to compress it. There are several bugs in this
+tool and its maintainer has seemingly abandoned the project.
The DMG tool has the ability to create DMGs from scratch as well, but this functionality is
broken. Only the compression feature is currently used. Ideally, the creation could be fixed
-and `genisoimage` would no longer be necessary.
+and `xorrisofs` would no longer be necessary.
Background images and other features can be added to DMG files by inserting a
-`.DS_Store` before creation. This is generated by the script `contrib/macdeploy/custom_dsstore.py`.
+`.DS_Store` during creation.
As of OS X 10.9 Mavericks, using an Apple-blessed key to sign binaries is a requirement in
order to satisfy the new Gatekeeper requirements. Because this private key cannot be
diff --git a/contrib/macdeploy/custom_dsstore.py b/contrib/macdeploy/custom_dsstore.py
deleted file mode 100755
index dc1c1882dd..0000000000
--- a/contrib/macdeploy/custom_dsstore.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2013-2018 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 biplist
-from ds_store import DSStore
-from mac_alias import Alias
-import sys
-
-output_file = sys.argv[1]
-package_name_ns = sys.argv[2]
-
-ds = DSStore.open(output_file, 'w+')
-ds['.']['bwsp'] = {
- 'ShowStatusBar': False,
- 'WindowBounds': '{{300, 280}, {500, 343}}',
- 'ContainerShowSidebar': False,
- 'SidebarWidth': 0,
- 'ShowTabView': False,
- 'PreviewPaneVisibility': False,
- 'ShowToolbar': False,
- 'ShowSidebar': False,
- 'ShowPathbar': True
-}
-
-icvp = {
- 'gridOffsetX': 0.0,
- 'textSize': 12.0,
- 'viewOptionsVersion': 1,
- 'backgroundImageAlias': b'\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00',
- 'backgroundColorBlue': 1.0,
- 'iconSize': 96.0,
- 'backgroundColorGreen': 1.0,
- 'arrangeBy': 'none',
- 'showIconPreview': True,
- 'gridSpacing': 100.0,
- 'gridOffsetY': 0.0,
- 'showItemInfo': False,
- 'labelOnBottom': True,
- 'backgroundType': 2,
- 'backgroundColorRed': 1.0
-}
-alias = Alias.from_bytes(icvp['backgroundImageAlias'])
-alias.volume.name = package_name_ns
-alias.volume.posix_path = '/Volumes/' + package_name_ns
-alias.volume.disk_image_alias.target.filename = package_name_ns + '.temp.dmg'
-alias.volume.disk_image_alias.target.carbon_path = 'Macintosh HD:Users:\x00bitcoinuser:\x00Documents:\x00bitcoin:\x00bitcoin:\x00' + package_name_ns + '.temp.dmg'
-alias.volume.disk_image_alias.target.posix_path = 'Users/bitcoinuser/Documents/bitcoin/bitcoin/' + package_name_ns + '.temp.dmg'
-alias.target.carbon_path = package_name_ns + ':.background:\x00background.tiff'
-icvp['backgroundImageAlias'] = biplist.Data(alias.to_bytes())
-ds['.']['icvp'] = icvp
-
-ds['.']['vSrn'] = ('long', 1)
-
-ds['Applications']['Iloc'] = (370, 156)
-ds['Bitcoin-Qt.app']['Iloc'] = (128, 156)
-
-ds.flush()
-ds.close()
diff --git a/contrib/macdeploy/fancy.plist b/contrib/macdeploy/fancy.plist
deleted file mode 100644
index ef277a7f14..0000000000
--- a/contrib/macdeploy/fancy.plist
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>window_bounds</key>
- <array>
- <integer>300</integer>
- <integer>300</integer>
- <integer>800</integer>
- <integer>620</integer>
- </array>
- <key>background_picture</key>
- <string>background.tiff</string>
- <key>icon_size</key>
- <integer>96</integer>
- <key>applications_symlink</key>
- <true/>
- <key>items_position</key>
- <dict>
- <key>Applications</key>
- <array>
- <integer>370</integer>
- <integer>156</integer>
- </array>
- <key>Bitcoin-Qt.app</key>
- <array>
- <integer>128</integer>
- <integer>156</integer>
- </array>
- </dict>
-</dict>
-</plist>
diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus
index d8088aa123..9bf3305288 100755
--- a/contrib/macdeploy/macdeployqtplus
+++ b/contrib/macdeploy/macdeployqtplus
@@ -16,9 +16,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import subprocess, sys, re, os, shutil, stat, os.path, time
-from string import Template
+import plistlib
+import sys, re, os, shutil, stat, os.path
from argparse import ArgumentParser
+from ds_store import DSStore
+from mac_alias import Alias
+from pathlib import Path
+from subprocess import PIPE, run
from typing import List, Optional
# This is ported from the original macdeployqt with modifications
@@ -49,28 +53,18 @@ class FrameworkInfo(object):
return False
def __str__(self):
- return """ Framework name: {}
- Framework directory: {}
- Framework path: {}
- Binary name: {}
- Binary directory: {}
- Binary path: {}
- Version: {}
- Install name: {}
- Deployed install name: {}
- Source file Path: {}
- Deployed Directory (relative to bundle): {}
-""".format(self.frameworkName,
- self.frameworkDirectory,
- self.frameworkPath,
- self.binaryName,
- self.binaryDirectory,
- self.binaryPath,
- self.version,
- self.installName,
- self.deployedInstallName,
- self.sourceFilePath,
- self.destinationDirectory)
+ return f""" Framework name: {frameworkName}
+ Framework directory: {self.frameworkDirectory}
+ Framework path: {self.frameworkPath}
+ Binary name: {self.binaryName}
+ Binary directory: {self.binaryDirectory}
+ Binary path: {self.binaryPath}
+ Version: {self.version}
+ Install name: {self.installName}
+ Deployed install name: {self.deployedInstallName}
+ Source file Path: {self.sourceFilePath}
+ Deployed Directory (relative to bundle): {self.destinationDirectory}
+"""
def isDylib(self):
return self.frameworkName.endswith(".dylib")
@@ -97,7 +91,7 @@ class FrameworkInfo(object):
m = cls.reOLine.match(line)
if m is None:
- raise RuntimeError("otool line could not be parsed: " + line)
+ raise RuntimeError(f"otool line could not be parsed: {line}")
path = m.group(1)
@@ -117,7 +111,7 @@ class FrameworkInfo(object):
info.version = "-"
info.installName = path
- info.deployedInstallName = "@executable_path/../Frameworks/" + info.binaryName
+ info.deployedInstallName = f"@executable_path/../Frameworks/{info.binaryName}"
info.sourceFilePath = path
info.destinationDirectory = cls.bundleFrameworkDirectory
else:
@@ -129,7 +123,7 @@ class FrameworkInfo(object):
break
i += 1
if i == len(parts):
- raise RuntimeError("Could not find .framework or .dylib in otool line: " + line)
+ raise RuntimeError(f"Could not find .framework or .dylib in otool line: {line}")
info.frameworkName = parts[i]
info.frameworkDirectory = "/".join(parts[:i])
@@ -140,7 +134,7 @@ class FrameworkInfo(object):
info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName)
info.version = parts[i+2]
- info.deployedInstallName = "@executable_path/../Frameworks/" + os.path.join(info.frameworkName, info.binaryPath)
+ info.deployedInstallName = f"@executable_path/../Frameworks/{os.path.join(info.frameworkName, info.binaryPath)}"
info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory)
info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources")
@@ -154,10 +148,10 @@ class FrameworkInfo(object):
class ApplicationBundleInfo(object):
def __init__(self, path: str):
self.path = path
- appName = "Bitcoin-Qt"
- self.binaryPath = os.path.join(path, "Contents", "MacOS", appName)
+ # for backwards compatibility reasons, this must remain as Bitcoin-Qt
+ self.binaryPath = os.path.join(path, "Contents", "MacOS", "Bitcoin-Qt")
if not os.path.exists(self.binaryPath):
- raise RuntimeError("Could not find bundle binary for " + path)
+ raise RuntimeError(f"Could not find bundle binary for {path}")
self.resourcesPath = os.path.join(path, "Contents", "Resources")
self.pluginPath = os.path.join(path, "Contents", "PlugIns")
@@ -181,30 +175,26 @@ class DeploymentInfo(object):
self.pluginPath = pluginPath
def usesFramework(self, name: str) -> bool:
- nameDot = "{}.".format(name)
- libNameDot = "lib{}.".format(name)
for framework in self.deployedFrameworks:
if framework.endswith(".framework"):
- if framework.startswith(nameDot):
+ if framework.startswith(f"{name}."):
return True
elif framework.endswith(".dylib"):
- if framework.startswith(libNameDot):
+ if framework.startswith(f"lib{name}."):
return True
return False
def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
- if verbose >= 3:
- print("Inspecting with otool: " + binaryPath)
+ if verbose:
+ print(f"Inspecting with otool: {binaryPath}")
otoolbin=os.getenv("OTOOL", "otool")
- otool = subprocess.Popen([otoolbin, "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
- o_stdout, o_stderr = otool.communicate()
+ otool = run([otoolbin, "-L", binaryPath], stdout=PIPE, stderr=PIPE, universal_newlines=True)
if otool.returncode != 0:
- if verbose >= 1:
- sys.stderr.write(o_stderr)
- sys.stderr.flush()
- raise RuntimeError("otool failed with return code {}".format(otool.returncode))
+ sys.stderr.write(otool.stderr)
+ sys.stderr.flush()
+ raise RuntimeError(f"otool failed with return code {otool.returncode}")
- otoolLines = o_stdout.split("\n")
+ otoolLines = otool.stdout.split("\n")
otoolLines.pop(0) # First line is the inspected binary
if ".framework" in binaryPath or binaryPath.endswith(".dylib"):
otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency.
@@ -214,7 +204,7 @@ def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
line = line.replace("@loader_path", os.path.dirname(binaryPath))
info = FrameworkInfo.fromOtoolLibraryLine(line.strip())
if info is not None:
- if verbose >= 3:
+ if verbose:
print("Found framework:")
print(info)
libraries.append(info)
@@ -223,10 +213,10 @@ def getFrameworks(binaryPath: str, verbose: int) -> List[FrameworkInfo]:
def runInstallNameTool(action: str, *args):
installnametoolbin=os.getenv("INSTALLNAMETOOL", "install_name_tool")
- subprocess.check_call([installnametoolbin, "-"+action] + list(args))
+ run([installnametoolbin, "-"+action] + list(args), check=True)
def changeInstallName(oldName: str, newName: str, binaryPath: str, verbose: int):
- if verbose >= 3:
+ if verbose:
print("Using install_name_tool:")
print(" in", binaryPath)
print(" change reference", oldName)
@@ -234,7 +224,7 @@ def changeInstallName(oldName: str, newName: str, binaryPath: str, verbose: int)
runInstallNameTool("change", oldName, newName, binaryPath)
def changeIdentification(id: str, binaryPath: str, verbose: int):
- if verbose >= 3:
+ if verbose:
print("Using install_name_tool:")
print(" change identification in", binaryPath)
print(" to", id)
@@ -242,22 +232,22 @@ def changeIdentification(id: str, binaryPath: str, verbose: int):
def runStrip(binaryPath: str, verbose: int):
stripbin=os.getenv("STRIP", "strip")
- if verbose >= 3:
+ if verbose:
print("Using strip:")
print(" stripped", binaryPath)
- subprocess.check_call([stripbin, "-x", binaryPath])
+ run([stripbin, "-x", binaryPath], check=True)
def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional[str]:
if framework.sourceFilePath.startswith("Qt"):
#standard place for Nokia Qt installer's frameworks
- fromPath = "/Library/Frameworks/" + framework.sourceFilePath
+ fromPath = f"/Library/Frameworks/{framework.sourceFilePath}"
else:
fromPath = framework.sourceFilePath
toDir = os.path.join(path, framework.destinationDirectory)
toPath = os.path.join(toDir, framework.binaryName)
if not os.path.exists(fromPath):
- raise RuntimeError("No file at " + fromPath)
+ raise RuntimeError(f"No file at {fromPath}")
if os.path.exists(toPath):
return None # Already there
@@ -266,7 +256,7 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
os.makedirs(toDir)
shutil.copy2(fromPath, toPath)
- if verbose >= 3:
+ if verbose:
print("Copied:", fromPath)
print(" to:", toPath)
@@ -280,13 +270,12 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
linkto = framework.version
if not os.path.exists(linkfrom):
os.symlink(linkto, linkfrom)
- if verbose >= 2:
- print("Linked:", linkfrom, "->", linkto)
+ print("Linked:", linkfrom, "->", linkto)
fromResourcesDir = framework.sourceResourcesDirectory
if os.path.exists(fromResourcesDir):
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True)
- if verbose >= 3:
+ if verbose:
print("Copied resources:", fromResourcesDir)
print(" to:", toResourcesDir)
fromContentsDir = framework.sourceVersionContentsDirectory
@@ -295,7 +284,7 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
if os.path.exists(fromContentsDir):
toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory)
shutil.copytree(fromContentsDir, toContentsDir, symlinks=True)
- if verbose >= 3:
+ if verbose:
print("Copied Contents:", fromContentsDir)
print(" to:", toContentsDir)
elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout)
@@ -303,7 +292,7 @@ def copyFramework(framework: FrameworkInfo, path: str, verbose: int) -> Optional
qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib")
if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath):
shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True)
- if verbose >= 3:
+ if verbose:
print("Copied for libQtGui:", qtMenuNibSourcePath)
print(" to:", qtMenuNibDestinationPath)
@@ -317,16 +306,14 @@ def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPat
framework = frameworks.pop(0)
deploymentInfo.deployedFrameworks.append(framework.frameworkName)
- if verbose >= 2:
- print("Processing", framework.frameworkName, "...")
+ print("Processing", framework.frameworkName, "...")
# Get the Qt path from one of the Qt frameworks
if deploymentInfo.qtPath is None and framework.isQtFramework():
deploymentInfo.detectQtPath(framework.frameworkDirectory)
if framework.installName.startswith("@executable_path") or framework.installName.startswith(bundlePath):
- if verbose >= 2:
- print(framework.frameworkName, "already deployed, skipping.")
+ print(framework.frameworkName, "already deployed, skipping.")
continue
# install_name_tool the new id into the binary
@@ -357,8 +344,8 @@ def deployFrameworks(frameworks: List[FrameworkInfo], bundlePath: str, binaryPat
def deployFrameworksForAppBundle(applicationBundle: ApplicationBundleInfo, strip: bool, verbose: int) -> DeploymentInfo:
frameworks = getFrameworks(applicationBundle.binaryPath, verbose)
- if len(frameworks) == 0 and verbose >= 1:
- print("Warning: Could not find any external frameworks to deploy in {}.".format(applicationBundle.path))
+ if len(frameworks) == 0:
+ print(f"Warning: Could not find any external frameworks to deploy in {applicationBundle.path}.")
return DeploymentInfo()
else:
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
@@ -477,8 +464,7 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme
plugins.append((pluginDirectory, pluginName))
for pluginDirectory, pluginName in plugins:
- if verbose >= 2:
- print("Processing plugin", os.path.join(pluginDirectory, pluginName), "...")
+ print("Processing plugin", os.path.join(pluginDirectory, pluginName), "...")
sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName)
destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory)
@@ -487,7 +473,7 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme
destinationPath = os.path.join(destinationDirectory, pluginName)
shutil.copy2(sourcePath, destinationPath)
- if verbose >= 3:
+ if verbose:
print("Copied:", sourcePath)
print(" to:", destinationPath)
@@ -503,146 +489,50 @@ def deployPlugins(appBundleInfo: ApplicationBundleInfo, deploymentInfo: Deployme
if dependency.frameworkName not in deploymentInfo.deployedFrameworks:
deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo)
-qt_conf="""[Paths]
-Translations=Resources
-Plugins=PlugIns
-"""
-
ap = ArgumentParser(description="""Improved version of macdeployqt.
Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file.
Note, that the "dist" folder will be deleted before deploying on each run.
-Optionally, Qt translation files (.qm) and additional resources can be added to the bundle.
-
-Also optionally signs the .app bundle; set the CODESIGNARGS environment variable to pass arguments
-to the codesign tool.
-E.g. CODESIGNARGS='--sign "Developer ID Application: ..." --keychain /encrypted/foo.keychain'""")
+Optionally, Qt translation files (.qm) can be added to the bundle.""")
ap.add_argument("app_bundle", nargs=1, metavar="app-bundle", help="application bundle to be deployed")
-ap.add_argument("-verbose", type=int, nargs=1, default=[1], metavar="<0-3>", help="0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug")
+ap.add_argument("appname", nargs=1, metavar="appname", help="name of the app being deployed")
+ap.add_argument("-verbose", nargs="?", const=True, help="Output additional debugging information")
ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment")
ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries")
-ap.add_argument("-sign", dest="sign", action="store_true", default=False, help="sign .app bundle with codesign tool")
-ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image; if basename is not specified, a camel-cased version of the app name is used")
-ap.add_argument("-fancy", nargs=1, metavar="plist", default=[], help="make a fancy looking disk image using the given plist file with instructions; requires -dmg to work")
-ap.add_argument("-add-qt-tr", nargs=1, metavar="languages", default=[], help="add Qt translation files to the bundle's resources; the language list must be separated with commas, not with whitespace")
-ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translation files")
-ap.add_argument("-add-resources", nargs="+", metavar="path", default=[], help="list of additional files or folders to be copied into the bundle's resources; must be the last argument")
-ap.add_argument("-volname", nargs=1, metavar="volname", default=[], help="custom volume name for dmg")
+ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image")
+ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translations. Base translations will automatically be added to the bundle's resources.")
config = ap.parse_args()
-verbose = config.verbose[0]
+verbose = config.verbose
# ------------------------------------------------
app_bundle = config.app_bundle[0]
+appname = config.appname[0]
if not os.path.exists(app_bundle):
- if verbose >= 1:
- sys.stderr.write("Error: Could not find app bundle \"{}\"\n".format(app_bundle))
+ sys.stderr.write(f"Error: Could not find app bundle \"{app_bundle}\"\n")
sys.exit(1)
-app_bundle_name = os.path.splitext(os.path.basename(app_bundle))[0]
-
-# ------------------------------------------------
-translations_dir = None
-if config.translations_dir and config.translations_dir[0]:
- if os.path.exists(config.translations_dir[0]):
- translations_dir = config.translations_dir[0]
- else:
- if verbose >= 1:
- sys.stderr.write("Error: Could not find translation dir \"{}\"\n".format(translations_dir))
- sys.exit(1)
-# ------------------------------------------------
-
-for p in config.add_resources:
- if verbose >= 3:
- print("Checking for \"%s\"..." % p)
- if not os.path.exists(p):
- if verbose >= 1:
- sys.stderr.write("Error: Could not find additional resource file \"{}\"\n".format(p))
- sys.exit(1)
-
-# ------------------------------------------------
-
-if len(config.fancy) == 1:
- if verbose >= 3:
- print("Fancy: Importing plistlib...")
- try:
- import plistlib
- except ImportError:
- if verbose >= 1:
- sys.stderr.write("Error: Could not import plistlib which is required for fancy disk images.\n")
- sys.exit(1)
-
- p = config.fancy[0]
- if verbose >= 3:
- print("Fancy: Loading \"{}\"...".format(p))
- if not os.path.exists(p):
- if verbose >= 1:
- sys.stderr.write("Error: Could not find fancy disk image plist at \"{}\"\n".format(p))
- sys.exit(1)
-
- try:
- fancy = plistlib.readPlist(p)
- except:
- if verbose >= 1:
- sys.stderr.write("Error: Could not parse fancy disk image plist at \"{}\"\n".format(p))
- sys.exit(1)
-
- try:
- assert "window_bounds" not in fancy or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4)
- assert "background_picture" not in fancy or isinstance(fancy["background_picture"], str)
- assert "icon_size" not in fancy or isinstance(fancy["icon_size"], int)
- assert "applications_symlink" not in fancy or isinstance(fancy["applications_symlink"], bool)
- if "items_position" in fancy:
- assert isinstance(fancy["items_position"], dict)
- for key, value in fancy["items_position"].items():
- assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int)
- except:
- if verbose >= 1:
- sys.stderr.write("Error: Bad format of fancy disk image plist at \"{}\"\n".format(p))
- sys.exit(1)
-
- if "background_picture" in fancy:
- bp = fancy["background_picture"]
- if verbose >= 3:
- print("Fancy: Resolving background picture \"{}\"...".format(bp))
- if not os.path.exists(bp):
- bp = os.path.join(os.path.dirname(p), bp)
- if not os.path.exists(bp):
- if verbose >= 1:
- sys.stderr.write("Error: Could not find background picture at \"{}\" or \"{}\"\n".format(fancy["background_picture"], bp))
- sys.exit(1)
- else:
- fancy["background_picture"] = bp
-else:
- fancy = None
-
# ------------------------------------------------
if os.path.exists("dist"):
- if verbose >= 2:
- print("+ Removing old dist folder +")
-
+ print("+ Removing existing dist folder +")
shutil.rmtree("dist")
-# ------------------------------------------------
-
-if len(config.volname) == 1:
- volname = config.volname[0]
-else:
- volname = app_bundle_name
+if os.path.exists(appname + ".dmg"):
+ print("+ Removing existing DMG +")
+ os.unlink(appname + ".dmg")
# ------------------------------------------------
target = os.path.join("dist", "Bitcoin-Qt.app")
-if verbose >= 2:
- print("+ Copying source bundle +")
-if verbose >= 3:
+print("+ Copying source bundle +")
+if verbose:
print(app_bundle, "->", target)
os.mkdir("dist")
@@ -652,257 +542,154 @@ applicationBundle = ApplicationBundleInfo(target)
# ------------------------------------------------
-if verbose >= 2:
- print("+ Deploying frameworks +")
+print("+ Deploying frameworks +")
try:
deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose)
if deploymentInfo.qtPath is None:
deploymentInfo.qtPath = os.getenv("QTDIR", None)
if deploymentInfo.qtPath is None:
- if verbose >= 1:
- sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n")
+ sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n")
config.plugins = False
except RuntimeError as e:
- if verbose >= 1:
- sys.stderr.write("Error: {}\n".format(str(e)))
+ sys.stderr.write(f"Error: {str(e)}\n")
sys.exit(1)
# ------------------------------------------------
if config.plugins:
- if verbose >= 2:
- print("+ Deploying plugins +")
+ print("+ Deploying plugins +")
try:
deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose)
except RuntimeError as e:
- if verbose >= 1:
- sys.stderr.write("Error: {}\n".format(str(e)))
+ sys.stderr.write(f"Error: {str(e)}\n")
sys.exit(1)
# ------------------------------------------------
-if len(config.add_qt_tr) == 0:
- add_qt_tr = []
-else:
- if translations_dir is not None:
- qt_tr_dir = translations_dir
- else:
- if deploymentInfo.qtPath is not None:
- qt_tr_dir = os.path.join(deploymentInfo.qtPath, "translations")
- else:
- sys.stderr.write("Error: Could not find Qt translation path\n")
- sys.exit(1)
- add_qt_tr = ["qt_{}.qm".format(lng) for lng in config.add_qt_tr[0].split(",")]
- for lng_file in add_qt_tr:
- p = os.path.join(qt_tr_dir, lng_file)
- if verbose >= 3:
- print("Checking for \"{}\"...".format(p))
- if not os.path.exists(p):
- if verbose >= 1:
- sys.stderr.write("Error: Could not find Qt translation file \"{}\"\n".format(lng_file))
- sys.exit(1)
+if config.translations_dir:
+ if not Path(config.translations_dir[0]).exists():
+ sys.stderr.write(f"Error: Could not find translation dir \"{config.translations_dir[0]}\"\n")
+ sys.exit(1)
+
+print("+ Adding Qt translations +")
+
+translations = Path(config.translations_dir[0])
+
+regex = re.compile('qt_[a-z]*(.qm|_[A-Z]*.qm)')
+
+lang_files = [x for x in translations.iterdir() if regex.match(x.name)]
+
+for file in lang_files:
+ if verbose:
+ print(file.as_posix(), "->", os.path.join(applicationBundle.resourcesPath, file.name))
+ shutil.copy2(file.as_posix(), os.path.join(applicationBundle.resourcesPath, file.name))
# ------------------------------------------------
-if verbose >= 2:
- print("+ Installing qt.conf +")
+print("+ Installing qt.conf +")
+
+qt_conf="""[Paths]
+Translations=Resources
+Plugins=PlugIns
+"""
with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f:
f.write(qt_conf.encode())
# ------------------------------------------------
-if len(add_qt_tr) > 0 and verbose >= 2:
- print("+ Adding Qt translations +")
-
-for lng_file in add_qt_tr:
- if verbose >= 3:
- print(os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file))
- shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file))
+print("+ Generating .DS_Store +")
+
+output_file = os.path.join("dist", ".DS_Store")
+
+ds = DSStore.open(output_file, 'w+')
+
+ds['.']['bwsp'] = {
+ 'WindowBounds': '{{300, 280}, {500, 343}}',
+ 'PreviewPaneVisibility': False,
+}
+
+icvp = {
+ 'gridOffsetX': 0.0,
+ 'textSize': 12.0,
+ 'viewOptionsVersion': 1,
+ 'backgroundImageAlias': b'\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00',
+ 'backgroundColorBlue': 1.0,
+ 'iconSize': 96.0,
+ 'backgroundColorGreen': 1.0,
+ 'arrangeBy': 'none',
+ 'showIconPreview': True,
+ 'gridSpacing': 100.0,
+ 'gridOffsetY': 0.0,
+ 'showItemInfo': False,
+ 'labelOnBottom': True,
+ 'backgroundType': 2,
+ 'backgroundColorRed': 1.0
+}
+alias = Alias().from_bytes(icvp['backgroundImageAlias'])
+alias.volume.name = appname
+alias.volume.posix_path = '/Volumes/' + appname
+icvp['backgroundImageAlias'] = alias.to_bytes()
+ds['.']['icvp'] = icvp
+
+ds['.']['vSrn'] = ('long', 1)
+
+ds['Applications']['Iloc'] = (370, 156)
+ds['Bitcoin-Qt.app']['Iloc'] = (128, 156)
+
+ds.flush()
+ds.close()
# ------------------------------------------------
-if len(config.add_resources) > 0 and verbose >= 2:
- print("+ Adding additional resources +")
+if config.dmg is not None:
-for p in config.add_resources:
- t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p))
- if verbose >= 3:
- print(p, "->", t)
- if os.path.isdir(p):
- shutil.copytree(p, t, symlinks=True)
- else:
- shutil.copy2(p, t)
+ print("+ Preparing .dmg disk image +")
-# ------------------------------------------------
+ if verbose:
+ print("Determining size of \"dist\"...")
+ size = 0
+ for path, dirs, files in os.walk("dist"):
+ for file in files:
+ size += os.path.getsize(os.path.join(path, file))
+ size += int(size * 0.15)
-if config.sign and 'CODESIGNARGS' not in os.environ:
- print("You must set the CODESIGNARGS environment variable. Skipping signing.")
-elif config.sign:
- if verbose >= 1:
- print("Code-signing app bundle {}".format(target))
- subprocess.check_call("codesign --force {} {}".format(os.environ['CODESIGNARGS'], target), shell=True)
+ if verbose:
+ print("Creating temp image for modification...")
-# ------------------------------------------------
+ tempname: str = appname + ".temp.dmg"
-if config.dmg is not None:
+ run(["hdiutil", "create", tempname, "-srcfolder", "dist", "-format", "UDRW", "-size", str(size), "-volname", appname], check=True, universal_newlines=True)
- def runHDIUtil(verb: str, image_basename: str, **kwargs) -> int:
- hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"]
- if "capture_stdout" in kwargs:
- del kwargs["capture_stdout"]
- run = subprocess.check_output
- else:
- if verbose < 2:
- hdiutil_args.append("-quiet")
- elif verbose >= 3:
- hdiutil_args.append("-verbose")
- run = subprocess.check_call
-
- for key, value in kwargs.items():
- hdiutil_args.append("-" + key)
- if value is not True:
- hdiutil_args.append(str(value))
-
- return run(hdiutil_args, universal_newlines=True)
-
- if verbose >= 2:
- if fancy is None:
- print("+ Creating .dmg disk image +")
- else:
- print("+ Preparing .dmg disk image +")
-
- if config.dmg != "":
- dmg_name = config.dmg
- else:
- spl = app_bundle_name.split(" ")
- dmg_name = spl[0] + "".join(p.capitalize() for p in spl[1:])
-
- if fancy is None:
- try:
- runHDIUtil("create", dmg_name, srcfolder="dist", format="UDBZ", volname=volname, ov=True)
- except subprocess.CalledProcessError as e:
- sys.exit(e.returncode)
- else:
- if verbose >= 3:
- print("Determining size of \"dist\"...")
- size = 0
- for path, dirs, files in os.walk("dist"):
- for file in files:
- size += os.path.getsize(os.path.join(path, file))
- size += int(size * 0.15)
-
- if verbose >= 3:
- print("Creating temp image for modification...")
- try:
- runHDIUtil("create", dmg_name + ".temp", srcfolder="dist", format="UDRW", size=size, volname=volname, ov=True)
- except subprocess.CalledProcessError as e:
- sys.exit(e.returncode)
-
- if verbose >= 3:
- print("Attaching temp image...")
- try:
- output = runHDIUtil("attach", dmg_name + ".temp", readwrite=True, noverify=True, noautoopen=True, capture_stdout=True)
- except subprocess.CalledProcessError as e:
- sys.exit(e.returncode)
-
- m = re.search(r"/Volumes/(.+$)", output)
- disk_root = m.group(0)
- disk_name = m.group(1)
-
- if verbose >= 2:
- print("+ Applying fancy settings +")
-
- if "background_picture" in fancy:
- bg_path = os.path.join(disk_root, ".background", os.path.basename(fancy["background_picture"]))
- os.mkdir(os.path.dirname(bg_path))
- if verbose >= 3:
- print(fancy["background_picture"], "->", bg_path)
- shutil.copy2(fancy["background_picture"], bg_path)
- else:
- bg_path = None
-
- if fancy.get("applications_symlink", False):
- os.symlink("/Applications", os.path.join(disk_root, "Applications"))
-
- # The Python appscript package broke with OSX 10.8 and isn't being fixed.
- # So we now build up an AppleScript string and use the osascript command
- # to make the .dmg file pretty:
- appscript = Template( """
- on run argv
- tell application "Finder"
- tell disk "$disk"
- open
- set current view of container window to icon view
- set toolbar visible of container window to false
- set statusbar visible of container window to false
- set the bounds of container window to {$window_bounds}
- set theViewOptions to the icon view options of container window
- set arrangement of theViewOptions to not arranged
- set icon size of theViewOptions to $icon_size
- $background_commands
- $items_positions
- close -- close/reopen works around a bug...
- open
- update without registering applications
- delay 5
- eject
- end tell
- end tell
- end run
- """)
-
- itemscript = Template('set position of item "${item}" of container window to {${position}}')
- items_positions = []
- if "items_position" in fancy:
- for name, position in fancy["items_position"].items():
- params = { "item" : name, "position" : ",".join([str(p) for p in position]) }
- items_positions.append(itemscript.substitute(params))
-
- params = {
- "disk" : volname,
- "window_bounds" : "300,300,800,620",
- "icon_size" : "96",
- "background_commands" : "",
- "items_positions" : "\n ".join(items_positions)
- }
- if "window_bounds" in fancy:
- params["window_bounds"] = ",".join([str(p) for p in fancy["window_bounds"]])
- if "icon_size" in fancy:
- params["icon_size"] = str(fancy["icon_size"])
- if bg_path is not None:
- # Set background file, then call SetFile to make it invisible.
- # (note: making it invisible first makes set background picture fail)
- bgscript = Template("""set background picture of theViewOptions to file ".background:$bgpic"
- do shell script "SetFile -a V /Volumes/$disk/.background/$bgpic" """)
- params["background_commands"] = bgscript.substitute({"bgpic" : os.path.basename(bg_path), "disk" : params["disk"]})
-
- s = appscript.substitute(params)
- if verbose >= 2:
- print("Running AppleScript:")
- print(s)
-
- p = subprocess.Popen(['osascript', '-'], stdin=subprocess.PIPE)
- p.communicate(input=s.encode('utf-8'))
- if p.returncode:
- print("Error running osascript.")
-
- if verbose >= 2:
- print("+ Finalizing .dmg disk image +")
- time.sleep(5)
-
- try:
- runHDIUtil("convert", dmg_name + ".temp", format="UDBZ", o=dmg_name + ".dmg", ov=True)
- except subprocess.CalledProcessError as e:
- sys.exit(e.returncode)
-
- os.unlink(dmg_name + ".temp.dmg")
+ if verbose:
+ print("Attaching temp image...")
+ output = run(["hdiutil", "attach", tempname, "-readwrite"], check=True, universal_newlines=True, stdout=PIPE).stdout
+
+ m = re.search(r"/Volumes/(.+$)", output)
+ disk_root = m.group(0)
+
+ print("+ Applying fancy settings +")
+
+ bg_path = os.path.join(disk_root, ".background", os.path.basename('background.tiff'))
+ os.mkdir(os.path.dirname(bg_path))
+ if verbose:
+ print('background.tiff', "->", bg_path)
+ shutil.copy2('background.tiff', bg_path)
+
+ os.symlink("/Applications", os.path.join(disk_root, "Applications"))
+
+ print("+ Finalizing .dmg disk image +")
+
+ run(["hdiutil", "detach", f"/Volumes/{appname}"], universal_newlines=True)
+
+ run(["hdiutil", "convert", tempname, "-format", "UDZO", "-o", appname, "-imagekey", "zlib-level=9"], check=True, universal_newlines=True)
+
+ os.unlink(tempname)
# ------------------------------------------------
-if verbose >= 2:
- print("+ Done +")
+print("+ Done +")
sys.exit(0)
diff --git a/contrib/seeds/.gitignore b/contrib/seeds/.gitignore
new file mode 100644
index 0000000000..e4a39d6093
--- /dev/null
+++ b/contrib/seeds/.gitignore
@@ -0,0 +1 @@
+seeds_main.txt
diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md
index 502c20d0d6..3bca094d3b 100644
--- a/contrib/seeds/README.md
+++ b/contrib/seeds/README.md
@@ -16,6 +16,12 @@ The seeds compiled into the release are created from sipa's DNS seed data, like
## Dependencies
-Ubuntu:
+Ubuntu, Debian:
sudo apt-get install python3-dnspython
+
+and/or for other operating systems:
+
+ pip install dnspython
+
+See https://dnspython.readthedocs.io/en/latest/installation.html for more information.
diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py
index e8698994f1..9be6a690a6 100755
--- a/contrib/seeds/makeseeds.py
+++ b/contrib/seeds/makeseeds.py
@@ -34,7 +34,8 @@ PATTERN_AGENT = re.compile(
r"0.17.(0|0.1|1|2|99)|"
r"0.18.(0|1|99)|"
r"0.19.(0|1|99)|"
- r"0.20.99"
+ r"0.20.(0|1|99)|"
+ r"0.21.99"
r")")
def parseline(line):
@@ -135,7 +136,7 @@ def lookup_asn(net, ip):
ipaddr = res.rstrip('.') # 2.0.0.1.4.8.6.0.b.0.0.2.0.0.2.3
prefix = '.origin6'
- asn = int([x.to_text() for x in dns.resolver.query('.'.join(
+ asn = int([x.to_text() for x in dns.resolver.resolve('.'.join(
reversed(ipaddr.split('.'))) + prefix + '.asn.cymru.com',
'TXT').response.answer][0].split('\"')[1].split(' ')[0])
return asn
diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt
index 58f6ad10b5..7b97436013 100644
--- a/contrib/seeds/nodes_main.txt
+++ b/contrib/seeds/nodes_main.txt
@@ -1,747 +1,1164 @@
2.39.173.126:8333
-2.57.38.133:8333
-2.92.39.39:15426
-2.230.146.163:8333
-5.2.74.175:8333
-5.8.18.29:8333
-5.39.222.39:8333
+3.14.168.201:48333
+4.36.112.44:8333
+5.8.18.31:8333
+5.14.200.167:8333
+5.56.20.2:8333
+5.102.146.99:8333
5.103.137.146:9333
5.128.87.126:8333
-5.149.250.76:8333
-5.182.39.200:8333
+5.133.65.82:8333
5.187.55.242:8333
5.188.62.24:8333
5.188.62.33:8333
-5.188.187.130:8333
-5.189.153.179:8333
-5.198.20.227:8333
5.199.133.193:8333
-5.254.82.130:8333
-13.237.147.15:8333
+8.38.89.152:8333
+13.231.20.249:8333
18.27.79.17:8333
20.184.15.116:8433
-23.17.160.159:8333
+23.28.205.97:8333
+23.106.252.230:8333
+23.175.0.202:8333
23.175.0.212:8333
+23.241.250.252:8333
23.245.24.154:8333
-24.76.122.108:8333
-24.96.73.156:8333
-24.96.125.57:8333
-24.155.196.27:8333
-24.203.88.167:8333
-24.233.245.188:8333
-24.246.31.205:8333
-31.6.98.94:8333
-31.14.201.156:8333
-31.25.241.224:8335
-31.43.140.190:8333
+24.86.184.66:8333
+24.116.246.9:8333
+24.141.34.166:8333
+24.155.196.246:8333
+24.157.130.222:8333
+24.188.176.255:8333
+24.237.70.53:8333
+27.124.4.67:8333
+31.17.70.80:8333
+31.21.8.32:8333
+31.45.118.10:8333
+31.132.17.56:8333
31.134.121.223:8333
-31.173.48.61:8333
-34.203.169.172:8333
-35.178.31.4:8333
-35.185.172.62:8333
-35.206.171.89:8333
-35.208.87.203:8333
-37.61.219.34:8333
-37.143.210.19:8333
-37.143.211.83:8333
-37.235.128.11:8333
-37.252.190.88:8333
-38.102.134.85:8333
-39.109.0.150:8333
-42.200.72.205:8333
-43.229.132.102:8333
+32.214.183.114:8333
+35.137.236.32:8333
+35.185.145.105:8333
+35.209.51.212:8333
+35.245.175.76:8333
+37.116.95.41:8333
+37.143.9.107:8333
+37.143.116.43:8333
+37.191.244.149:8333
+37.211.78.253:8333
+37.221.209.222:24333
+37.228.92.110:8333
+43.225.62.107:8333
+43.225.157.152:8333
45.36.184.6:8333
-45.58.49.35:8333
-45.76.18.47:8333
-45.115.239.108:8333
-46.23.87.218:8333
+45.48.168.16:8333
+45.85.85.8:8333
+45.85.85.9:8333
+45.129.180.214:8333
+45.149.78.128:8333
+45.151.125.218:8333
+45.154.255.46:8333
+45.155.157.239:8333
46.28.132.34:8333
+46.28.204.21:8333
46.32.50.98:8333
-46.36.97.10:8333
-46.38.237.108:8333
-46.39.129.82:8333
-46.160.195.121:8333
+46.59.13.35:8333
+46.128.40.173:8333
+46.128.140.193:8333
+46.146.248.89:8333
46.166.162.45:20001
-46.188.30.118:8333
+46.188.15.6:8333
+46.229.165.142:8333
46.229.238.187:8333
+46.249.83.82:8333
46.254.217.169:8333
-47.52.114.198:8885
-47.88.84.126:8333
-47.108.29.152:8333
-47.108.30.165:8333
+47.74.191.34:8333
+47.115.53.163:8333
+47.187.26.135:8333
47.222.103.234:8333
-49.245.50.224:8333
-50.53.250.162:8333
-50.225.198.67:6000
+47.253.5.99:8333
+49.232.82.76:8333
+49.247.215.43:8333
+50.2.13.166:8333
+50.34.39.72:8333
+50.45.232.189:8333
+50.68.104.92:8333
+51.68.36.57:8333
51.154.60.34:8333
-54.242.17.7:8333
-58.146.222.198:8333
+52.169.238.66:8333
+54.197.30.223:8333
+54.227.66.57:8333
58.158.0.86:8333
-59.149.205.197:8333
-60.251.129.61:8336
-61.155.5.4:8333
-62.45.4.139:8333
-62.97.244.242:8333
-62.109.18.23:8333
-62.133.194.156:8333
-62.138.0.217:8333
+58.171.135.242:8333
+58.229.208.158:8333
+60.244.109.19:8333
+62.38.75.208:8333
+62.74.143.11:8333
+62.80.227.49:8333
62.152.58.16:9421
-63.143.34.98:8333
-63.211.111.122:8333
-63.224.249.240:8333
-64.182.119.36:8333
-64.229.105.111:8333
-65.27.104.112:8333
-65.183.76.73:8333
-66.151.242.154:8335
-66.206.13.70:8333
+62.210.167.199:8333
+62.234.188.160:8333
+62.251.54.163:8333
+63.227.116.162:8333
+65.19.155.82:8333
+65.95.49.102:8333
+66.18.172.21:8333
66.240.237.155:8333
-66.240.237.172:8333
-67.205.140.145:8333
67.210.228.203:8333
-67.221.193.55:8333
-67.222.131.151:8333
-68.110.90.111:8333
-68.142.33.36:8333
-68.199.157.183:8333
-68.202.128.19:8333
-68.206.21.144:8333
69.30.215.42:8333
-69.55.234.74:8333
-69.59.18.22:8333
-69.145.122.160:8333
-69.175.49.230:8333
-70.64.48.41:8333
-71.33.232.126:8333
-71.73.18.32:8333
-71.146.114.111:8333
+69.59.18.206:8333
+69.64.33.71:8333
+69.119.193.9:8333
+69.209.23.72:8333
+70.123.125.237:8333
+70.185.56.136:8333
+71.38.90.235:8333
+72.12.73.70:8333
72.53.134.182:8333
-73.126.97.99:8333
-74.83.126.150:8333
-74.84.128.158:9333
-74.98.242.97:8333
+72.225.7.80:8333
+72.234.182.39:8333
+72.250.184.57:8333
+73.83.103.79:8333
74.118.137.119:8333
+74.133.100.74:8333
+74.215.219.214:8333
74.220.255.190:8333
-75.45.51.41:8333
75.158.39.231:8333
-76.11.17.187:8333
-76.84.79.211:8333
-76.167.179.75:8333
-77.53.158.137:8333
-77.119.229.106:8333
+77.53.53.196:8333
+77.70.16.245:8333
+77.105.87.97:8333
+77.120.113.69:8433
77.120.122.22:8433
-77.120.122.114:8433
-77.163.136.136:8333
-77.220.140.74:8333
+77.166.83.167:8333
77.247.178.130:8333
-78.128.62.52:8333
-78.128.79.22:8333
+78.27.139.13:8333
+78.63.28.146:8333
+78.83.103.4:8333
78.141.123.99:8333
-78.143.214.223:8333
-78.159.99.85:8333
79.77.33.131:8333
-79.120.70.47:8333
-79.142.129.218:8333
-79.175.125.210:8333
-80.47.156.43:8333
+79.77.133.30:8333
+79.101.1.25:8333
+79.117.192.229:8333
+79.133.228.55:8333
+79.146.21.163:8333
80.89.203.172:8001
80.93.213.246:8333
-80.111.142.213:8333
-80.147.82.165:8333
-80.211.191.11:8333
-80.211.245.151:8333
+80.192.98.110:8334
80.229.28.60:8333
-80.229.168.1:8333
+80.232.247.210:8333
+80.242.39.76:8333
80.253.94.252:8333
-81.4.102.69:8333
+81.0.198.25:8333
81.7.13.84:8333
-81.10.205.21:8333
81.117.225.245:8333
-81.177.157.81:39993
-81.235.185.150:8333
+81.135.137.225:8333
+81.171.22.143:8333
+81.191.233.134:8333
+81.232.78.75:8333
+81.242.91.23:8333
82.29.58.109:8333
-82.117.166.77:8333
-82.118.20.37:8333
-82.146.50.143:8333
-82.146.153.130:8333
+82.136.99.22:8333
82.149.97.25:17567
-82.169.130.61:8333
-82.181.179.230:8333
-82.181.218.229:8333
+82.165.19.48:8333
82.194.153.233:8333
-82.195.237.253:8333
-82.197.218.97:8333
+82.197.215.125:8333
82.199.102.10:8333
-82.199.102.133:8333
-82.202.197.224:8333
-82.217.245.7:8333
-82.221.111.136:8333
-83.89.27.50:8333
-83.89.250.69:8333
-83.167.27.4:8333
-83.208.254.182:8333
+82.200.205.30:8333
+82.202.68.231:8333
+82.221.128.31:8333
+82.228.6.131:8333
+83.85.139.94:8333
+83.99.245.20:8333
+83.137.41.10:8333
+83.174.209.87:8333
83.217.8.31:44420
-83.221.211.116:8335
-83.243.59.41:8333
-83.251.241.0:8333
84.38.3.249:8333
-84.40.94.170:8333
+84.38.185.122:8333
+84.92.92.247:8333
84.192.16.234:8333
-84.209.9.23:8333
-84.234.96.115:8333
-84.248.14.210:8333
-85.119.83.25:8333
-85.144.119.222:8333
-85.145.238.93:8333
+84.194.158.124:8333
+84.212.145.24:8333
+84.212.244.95:8333
+84.216.51.36:8333
+84.255.249.163:8333
+85.25.255.147:8333
+85.70.156.209:8333
+85.145.142.46:8333
+85.170.233.95:8333
85.184.138.108:8333
85.190.0.5:8333
-85.202.11.119:8333
-85.204.96.207:8333
-85.208.69.13:8333
-85.214.90.161:8333
-85.240.233.220:8333
+85.191.200.51:8333
+85.192.191.6:18500
+85.194.238.131:8333
+85.195.54.110:8333
+85.214.161.252:8333
+85.214.185.51:8333
85.241.106.203:8333
-86.15.38.61:8333
-86.76.7.132:8333
+85.246.168.252:8333
+86.56.238.247:8333
+87.61.90.230:8333
87.79.68.86:8333
87.79.94.221:8333
-87.118.116.237:8333
87.120.8.5:20008
-87.222.22.255:8333
-87.233.181.146:8333
87.246.46.132:8333
-87.249.207.89:8333
-88.86.116.140:8333
-88.86.116.142:8333
-88.88.13.249:8333
+87.247.111.222:8333
+88.84.222.252:8333
+88.86.243.241:8333
+88.87.93.52:1691
+88.119.197.200:8333
+88.129.253.94:8333
88.147.244.250:8333
-88.150.230.95:8333
-88.202.202.221:8333
88.208.3.195:8333
88.212.44.33:8333
-89.25.80.42:8333
-89.28.117.31:8333
+88.214.57.95:8333
89.106.199.38:8333
-89.142.75.60:8333
+89.108.126.228:8333
+89.115.120.43:8333
+89.133.68.65:8333
89.190.19.162:8333
-89.212.9.96:8333
-89.212.75.6:8333
-89.248.250.12:8333
-90.94.83.26:8333
+89.248.172.10:8333
+90.146.153.21:8333
90.182.165.18:8333
-91.185.198.234:8333
+91.106.188.229:8333
91.193.237.116:8333
91.204.99.178:8333
91.204.149.5:8333
-91.210.24.30:8333
-91.211.88.33:8333
-91.216.149.28:8333
-91.222.128.59:8333
-92.18.180.225:8333
-92.53.89.123:8333
-92.240.69.195:8333
+91.214.70.63:8333
+91.228.152.236:8333
+92.12.154.115:8333
92.249.143.44:8333
-92.255.176.109:8333
-93.57.81.162:8333
-93.90.193.195:8330
-93.90.207.46:8333
-93.115.26.186:20004
-93.115.240.26:8333
+93.12.66.98:8333
+93.46.54.4:8333
+93.115.20.130:8333
93.123.180.164:8333
-93.175.204.121:8333
-93.180.178.213:8333
+93.189.145.169:8333
+93.241.228.102:8333
94.19.7.55:8333
+94.19.128.204:8333
94.52.112.227:8333
-94.53.2.181:8333
-94.72.143.26:8333
-94.103.120.173:8333
-94.237.64.138:8333
-94.237.80.207:8333
-94.242.255.31:8333
-95.24.48.84:15426
-95.42.2.113:8333
+94.154.96.130:8333
+94.156.174.201:8333
+94.158.246.183:8333
+94.177.171.73:8333
+94.199.178.233:8100
+94.237.125.30:8333
+94.247.134.77:8333
+95.48.228.45:8333
95.69.249.63:8333
-95.79.35.133:8333
+95.82.146.70:8333
+95.83.73.31:8333
+95.84.164.43:8333
95.87.226.56:8333
-95.90.3.210:8333
95.110.234.93:8333
-95.156.252.34:8333
-95.211.189.3:8333
-95.217.9.207:8333
-96.9.80.109:8333
-96.245.218.247:8333
-97.104.206.3:8333
-98.29.195.204:8333
-99.231.196.126:8333
-101.100.174.24:8333
+95.163.71.126:8333
+95.164.65.194:8333
+95.174.66.211:8333
+95.211.174.137:8333
+95.216.11.156:8433
+96.47.114.108:8333
+97.84.232.105:8333
+97.99.205.241:8333
+98.25.193.114:8333
+99.115.25.13:8333
+101.32.19.184:8333
101.100.174.240:8333
+102.132.245.16:8333
103.14.244.190:8333
-103.37.205.47:8333
-103.60.109.184:20008
+103.76.48.5:8333
103.84.84.250:8335
-103.85.190.218:20000
-103.99.168.100:8333
-103.99.168.130:8333
-103.214.146.86:8333
+103.99.168.150:8333
+103.109.101.216:8333
+103.122.247.102:8333
+103.129.13.45:8333
+103.198.192.14:20008
+103.224.119.99:8333
+103.231.191.7:8333
+103.235.230.196:8333
104.171.242.155:8333
-104.199.184.15:8333
-104.244.223.151:8333
-105.29.76.194:8333
-107.150.45.18:8333
-107.180.77.21:8333
-108.58.252.82:8333
+104.238.220.199:8333
+106.163.158.127:8333
+107.150.41.179:8333
+107.159.93.103:8333
108.183.77.12:8333
-109.72.83.127:8333
+109.9.175.65:8333
109.99.63.159:8333
-109.109.36.19:8333
109.110.81.90:8333
-109.173.112.224:8333
-109.202.107.125:8333
-109.205.109.56:8333
-109.236.84.141:8333
-109.238.81.82:8333
+109.123.213.130:8333
+109.134.232.81:8333
+109.169.20.168:8333
+109.199.241.148:8333
+109.229.210.6:8333
+109.236.105.40:8333
109.248.206.13:8333
-111.40.4.103:8333
-111.90.140.217:8333
-111.90.158.212:8333
-112.213.103.98:8333
+111.42.74.65:8333
+111.90.140.179:8333
+112.215.205.236:8333
113.52.135.125:8333
+114.23.246.137:8333
115.47.141.250:8885
115.70.110.4:8333
-116.87.15.244:8333
+116.34.189.55:8333
+118.103.126.140:28333
+118.189.187.219:8333
+119.3.208.236:8333
+119.8.47.225:8333
119.17.151.61:8333
-119.171.134.87:8333
-121.18.238.39:8333
-121.78.223.186:8333
-121.98.205.102:8333
+120.25.24.30:8333
+120.241.34.10:8333
+121.98.205.100:8333
122.112.148.153:8339
122.116.42.140:8333
-124.160.119.93:8333
+124.217.235.180:8333
125.236.215.133:8333
129.13.189.212:8333
-129.97.243.18:8333
130.185.77.105:8333
-131.114.10.233:8333
-131.188.40.34:8333
-132.249.239.163:8333
-134.19.186.195:8333
-134.249.187.97:8333
-136.144.215.219:8333
+131.188.40.191:8333
+131.193.220.15:8333
+135.23.124.239:8333
+136.33.185.32:8333
+136.56.170.96:8333
137.226.34.46:8333
+138.229.26.42:8333
139.9.249.234:8333
141.101.8.36:8333
-143.89.121.207:8333
143.176.224.104:8333
+144.2.69.224:8333
144.34.161.65:18333
-147.253.70.208:8333
-148.66.50.82:8335
-153.92.127.216:8333
-153.120.115.15:8333
-154.52.98.2:8444
-155.4.116.169:8333
+144.91.116.44:8333
+144.137.29.181:8333
+148.66.50.50:8335
+148.72.150.231:8333
+148.170.212.44:8333
+149.167.99.190:8333
+154.92.16.191:8333
+154.221.27.21:8333
156.19.19.90:8333
-156.34.178.138:8333
-157.13.61.66:8333
-157.13.61.67:8333
+156.241.5.190:8333
+157.13.61.76:8333
+157.13.61.80:8333
+157.230.166.98:14391
+158.75.203.2:8333
+158.181.125.150:8333
158.181.226.33:8333
159.100.242.254:8333
159.100.248.234:8333
-159.253.98.209:8333
+159.138.87.18:8333
160.16.0.30:8333
-160.20.145.62:8333
+162.0.227.54:8333
+162.0.227.56:8333
162.62.18.226:8333
-162.62.26.218:8333
-162.209.88.174:8333
+162.209.1.233:8333
+162.243.175.86:8333
162.244.80.208:8333
+162.250.188.87:8333
+162.250.189.53:8333
163.158.202.112:8333
-163.172.181.191:8333
-166.62.100.55:8333
-167.114.35.12:8333
-168.62.167.209:8200
-168.235.74.110:8333
-168.235.90.188:8333
-170.249.37.243:8333
-172.99.120.113:8333
-173.21.218.95:8333
-173.51.177.2:8333
-173.95.72.234:8333
+163.158.243.230:8333
+165.73.62.31:8333
+166.62.82.103:32771
+166.70.94.106:8333
+167.86.90.239:8333
+169.44.34.203:8333
+172.93.101.73:8333
+172.105.7.47:8333
+173.23.103.30:8000
+173.53.79.6:8333
+173.70.12.86:8333
+173.89.28.137:8333
+173.176.184.54:8333
173.208.128.10:8333
-173.209.44.34:8333
-173.231.57.194:8333
+173.254.204.69:8333
173.255.204.124:8333
-174.65.135.60:8333
174.94.155.224:8333
-174.115.120.186:8333
-176.53.160.170:8333
-176.85.188.213:8333
+174.114.102.41:8333
+174.114.124.12:8333
+176.10.227.59:8333
+176.31.224.214:8333
+176.74.136.237:8333
176.99.2.207:8333
-176.121.14.157:8333
-176.122.157.173:8333
-176.126.85.34:8333
-176.198.120.197:8334
-178.61.141.198:8333
-178.119.183.34:8333
-178.234.29.184:8333
+176.106.191.2:8333
+176.160.228.9:8333
+176.191.182.3:8333
+176.212.185.153:8333
+176.241.137.183:8333
+177.38.215.73:8333
+178.16.222.146:8333
+178.132.2.246:8333
+178.143.191.171:8333
+178.148.172.209:8333
+178.148.226.180:8333
+178.150.96.46:8333
+178.182.227.50:8333
+178.236.137.63:8333
178.255.42.126:8333
-179.48.251.41:8333
-180.150.73.100:8333
-181.47.220.242:8333
-181.170.139.47:8333
+180.150.52.37:8333
+181.39.32.99:8333
+181.48.77.26:8333
+181.52.223.52:8333
+181.238.51.152:8333
+183.88.223.208:8333
183.110.220.210:30301
-183.230.93.139:8333
-184.95.58.164:8663
+184.95.58.166:8336
184.164.147.82:41333
-185.15.92.18:20993
-185.25.60.199:8333
-185.52.3.185:8333
-185.61.138.4:8333
+184.171.208.109:8333
+185.25.48.39:8333
+185.25.48.184:8333
185.64.116.15:8333
-185.83.110.53:8333
-185.83.214.123:8333
+185.80.219.132:8333
+185.85.3.140:8333
185.95.219.53:8333
-185.96.94.24:8333
-185.102.71.6:8333
-185.138.35.183:8333
-185.140.252.253:8333
-185.143.145.113:8333
+185.108.244.41:8333
+185.134.233.121:8333
+185.145.128.21:8333
185.148.3.227:8333
-185.157.160.220:8333
-185.163.44.44:8333
-185.176.221.32:8333
+185.153.196.240:8333
+185.158.114.184:8333
+185.165.168.196:8333
+185.181.230.74:8333
+185.185.26.141:8111
185.186.208.162:8333
-185.198.58.47:8333
-185.198.59.183:8333
-185.215.224.22:8333
-185.232.28.254:8333
-185.239.236.116:8333
+185.189.132.178:57780
+185.211.59.50:8333
+185.233.148.146:8333
+185.238.129.113:8333
+185.249.199.106:8333
185.251.161.54:8333
+187.189.153.136:8333
+188.37.24.190:8333
188.42.40.234:18333
-188.65.212.138:8333
-188.65.212.157:8333
+188.61.46.36:8333
188.68.45.143:8333
188.127.229.105:8333
-188.131.177.130:8333
+188.134.6.84:8333
188.134.8.36:8333
-188.134.88.5:8333
-188.138.17.92:8333
-188.150.157.11:8333
-188.208.111.62:8333
-188.231.177.149:8333
-190.2.145.177:8333
-190.104.249.44:8333
+188.214.129.65:20012
+188.230.168.114:8333
+189.34.14.93:8333
+189.207.46.32:8333
+190.211.204.68:8333
191.209.21.188:8333
192.3.11.20:8333
-192.3.11.24:8333
-192.34.56.59:8333
+192.3.185.210:8333
192.65.170.15:8333
192.65.170.50:8333
192.146.137.18:8333
-192.166.47.32:8333
-192.169.94.29:8333
+192.157.202.178:8333
192.227.80.83:8333
-192.254.65.126:8333
193.10.203.23:8334
-193.29.57.4:8333
+193.25.6.206:8333
+193.42.110.30:8333
193.58.196.212:8333
-193.59.41.11:8333
-193.84.116.22:8333
-193.108.131.43:8333
-193.148.71.10:8333
-193.169.244.190:8333
+193.106.28.8:8333
+193.189.190.123:8333
193.194.163.35:8333
193.194.163.53:8333
-194.5.159.197:8333
194.14.246.205:8333
-194.135.92.96:8333
+194.36.91.253:8333
+194.126.113.135:8333
194.135.135.69:8333
-194.158.92.150:8333
-194.187.251.163:31239
+195.56.63.4:8333
195.56.63.5:8333
-195.56.63.10:8333
195.67.139.54:8333
-195.95.225.17:8333
195.135.194.8:8333
-195.154.113.90:8333
-195.206.20.114:8333
+195.202.169.149:8333
195.206.105.42:8333
195.209.249.164:8333
-195.224.116.20:8333
198.1.231.6:8333
-198.251.83.19:8333
-199.48.83.58:8333
-199.96.50.211:8333
-199.188.204.25:8333
-199.192.20.201:8333
-200.76.194.7:8333
-200.87.116.213:8333
-202.28.194.82:8333
+198.200.43.215:8333
+199.182.184.204:8333
+199.247.7.208:8333
+199.247.249.188:8333
+200.7.252.118:8333
+200.20.186.254:8333
+200.83.166.136:8333
202.55.87.45:8333
+202.79.167.65:8333
+202.108.211.135:8333
+202.169.102.73:8333
203.130.48.117:8885
203.132.95.10:8333
-204.14.245.180:8333
-204.152.203.98:8333
-205.209.162.98:8333
-206.221.178.149:8333
+203.151.166.123:8333
+204.93.113.108:8333
+204.111.241.195:8333
+206.124.149.66:8333
+207.115.102.98:8333
+207.229.46.150:8333
+208.76.252.198:8333
+208.100.13.56:8333
+208.100.178.175:8333
208.110.99.105:8333
+209.6.210.179:8333
209.133.220.74:8333
-209.151.237.71:8333
-211.149.170.31:8333
-212.51.132.226:8333
-212.241.70.213:8333
-213.21.15.22:8333
-213.136.83.8:8333
-213.227.152.108:8333
-213.254.23.116:8333
-216.108.236.180:8333
-216.194.165.98:8333
+209.141.57.57:8333
+211.27.147.67:8333
+212.34.225.118:8333
+212.89.173.216:8333
+212.99.226.36:9020
+212.237.96.98:8333
+213.89.131.53:8333
+216.38.129.164:8333
+216.134.165.55:8333
+216.146.251.8:8333
+216.189.190.95:8333
+216.226.128.189:8333
216.236.164.82:8333
-217.16.185.165:8333
-217.21.24.146:8333
+217.19.216.210:8333
217.26.32.10:8333
217.64.47.138:8333
217.64.133.220:8333
217.92.55.246:8333
-217.172.244.9:8333
-218.75.140.45:8333
-219.75.122.47:8333
-220.233.138.130:8333
-221.130.29.230:18421
-222.122.49.40:8333
-222.186.169.1:8333
-222.222.43.29:8333
+218.31.113.245:8333
+218.255.242.114:8333
+220.133.39.61:8333
223.16.30.175:8333
+[2001:19f0:6001:306f:ec4:7aff:fe8f:66ec]:8333
[2001:1bc0:cc::a001]:8333
[2001:1c02:2f18:d00:b62e:99ff:fe49:d492]:8333
-[2001:250:200:7:d6a9:fcf4:e78d:2d82]:8333
-[2001:41c9:1:424::231]:8333
-[2001:41d0:1004:19b4::]:8333
-[2001:44b8:4195:1801:5c73:5d67:d2a6:9910]:8333
-[2001:470:88ff:2e::1]:8333
+[2001:4100:0:64::93]:8333
+[2001:4100:0:64:dcaf:afff:fe00:6707]:8333
[2001:470:a:c13::2]:8333
-[2001:4800:7821:101:be76:4eff:fe04:9f50]:8333
-[2001:4801:7819:74:b745:b9d5:ff10:aaec]:8333
-[2001:48d0:1:2163:0:ff:febe:5a80]:8333
+[2001:4801:7819:74:b745:b9d5:ff10:a61a]:8333
[2001:4ba0:fffa:5d::93]:8333
+[2001:610:1908:ff01:f816:3eff:fe33:2e32]:8333
[2001:638:a000:4140::ffff:191]:8333
+[2001:648:2800:131:4b1f:f6fc:20f7:f99f]:8333
[2001:678:7dc:8::2]:8333
-[2001:678:ec:1:250:56ff:fea7:47e9]:8333
-[2001:67c:10ec:2a49:8000::1082]:8333
+[2001:678:cc8::1:10:88]:20008
+[2001:67c:1220:80c::93e5:dd2]:8333
+[2001:67c:1220:80c:e5dc:ad0c:9289:c28f]:8333
[2001:67c:16dc:1201:5054:ff:fe17:4dac]:8333
-[2001:67c:21ec:1000::a]:8333
+[2001:67c:2354:2::22]:8333
[2001:67c:26b4:12:7ae3:b5ff:fe04:6f9c]:8333
-[2001:67c:2db8:6::45]:8333
-[2001:700:300:1513:29c7:2430:190e:ab59]:8333
+[2001:67c:2f0::20:fa]:8333
[2001:718:801:311:5054:ff:fe19:c483]:8333
-[2001:818:e245:f800:4df:2bdf:ecf5:eb60]:8333
+[2001:8d8:87c:7c00::99:3c1]:8333
[2001:8f1:1404:3700:8e49:715a:2e09:b634]:9444
-[2001:ba8:1f1:f069::2]:8333
-[2001:bb8:4008:20:648c:5eff:fe74:ce4]:8333
-[2001:da8:d800:821:a7d5:f5a7:530d:b71e]:8333
+[2001:b07:5d29:99a5:194b:3874:d65e:a90d]:8333
+[2001:ba8:1f1:f0fe::2]:8333
+[2001:bc8:1200:0:dac4:97ff:fe2a:3554]:20008
+[2001:da8:100d:22:10fa:d85f:10f2:21fd]:8333
+[2001:da8:8001:7a39:f035:7d:b99f:eb79]:8333
[2001:e42:103:100::30]:8333
-[2001:e68:7400:2:6854:419e:221c:82f3]:8333
-[2002:b610:1ca3::b610:1ca3]:8333
-[2002:b6ff:3dca::b6ff:3dca]:28364
-[2400:2651:42e0:3300:40b4:576d:d14c:65d4]:8333
+[2400:2412:103:c900:825:8f20:eaff:65c2]:8333
[2400:4052:e20:4f00:69fe:bb33:7b1c:a1ca]:8333
-[2401:2500:203:184::15]:8333
+[2401:1800:7800:105:be76:4eff:fe1c:b35]:8333
[2401:3900:2:1::2]:8333
-[2401:a400:3200:5600:14ee:f361:4bdc:1f7c]:8333
+[2401:b140::44:150]:8333
[2401:d002:4402:0:8f28:591a:6ea0:c683]:8333
-[2402:cb40:1000:504::dead]:8333
+[2403:6200:8821:3d68:195b:87e9:6819:d5c8]:8333
+[2405:6580:2140:3a00:c28c:983:364b:5d70]:8333
+[2405:9800:b911:a18a:58eb:cd3c:9d82:ea4a]:8333
[2405:aa00:2::40]:8333
[2409:10:ca20:1df0:224:e8ff:fe1f:60d9]:8333
-[2409:8a15:4a1a:2830:7285:c2ff:fe70:60a4]:8333
-[2409:8a1e:6938:d2c0:2e0:70ff:fe86:cb59]:8333
-[2409:8a28:421:2580:2e0:70ff:fe8b:13e]:8333
-[2409:8a28:421:2770:2e0:70ff:fe87:fecb]:8333
+[2409:8a1e:a9af:3660:1c5a:5b6b:8a2d:9848]:8333
+[2409:8a1e:a9af:3660:404:39ba:88f2:e8df]:8333
+[240b:10:9141:400:49b4:3a2e:1e5:84c]:8333
+[240d:1a:759:6000:a7b1:451a:8874:e1ac]:8333
[240d:1a:759:6000:ddab:3141:4da0:8878]:8333
-[2600:3c01::f03c:91ff:fecd:1b95]:8333
-[2600:6c40:7980:27:20a:f7ff:fe69:f4d5]:8333
-[2602:ffc5::ffc5:b844]:8333
-[2604:2d80:c808:857b:8d6:9e1c:7131:4bea]:8333
+[2600:8805:2400:14e:12dd:b1ff:fef2:3013]:8333
+[2601:602:8d80:b63:dc3e:24ff:fe92:5eb]:8333
+[2602:ffb6:4:2798:f816:3eff:fe2f:5441]:8333
+[2602:ffb6:4:739e:f816:3eff:fe00:c2b3]:8333
+[2602:ffb8::208:72:57:200]:8333
+[2604:1380:4111:9300::1]:8333
[2604:4300:a:2e:21b:21ff:fe11:392]:8333
+[2604:4500::2e06]:8112
+[2604:5500:706a:4000:fc79:b9bb:1d7:c325]:8333
[2604:5500:c134:4000::3fc]:32797
-[2604:5500:c2a3:7b00:cc6:373b:44a8:caa4]:8333
-[2604:6000:6e85:4a01:a82d:f9ff:fef5:28b9]:8333
-[2604:7780:303:80::80]:8333
+[2604:6800:5e11:162:5c8f:d2ff:fe26:146f]:8333
[2605:4d00::50]:8333
-[2605:9880:0:777:225:90ff:fefc:8958]:8333
+[2605:6400:20:13bf:df1d:181c:83bb:22e8]:8333
[2605:ae00:203::203]:8333
[2605:c000:2a0a:1::102]:8333
-[2605:e000:1127:8fc:ec63:a191:32c2:633c]:8333
-[2605:e200:d202:300:20c:29ff:fef1:85ec]:8333
-[2605:f700:100:400::131:5b54]:8333
-[2606:c680:0:b:3830:34ff:fe66:6663]:8333
-[2607:4480:2:1:38:102:69:70]:8333
-[2607:9280:b:73b:250:56ff:fe21:9c2f]:8333
-[2607:f128:40:1703::2]:8333
-[2607:f188:0:4:eef4:bbff:fecc:6668]:8333
-[2607:f2c0:e1e2:11:1044:9b7a:b81e:1d74]:8333
+[2607:f2c0:f00e:300::54]:8333
+[2607:f2f8:ad40:bc1::1]:8333
[2607:f470:8:1048:ae1f:6bff:fe70:7240]:8333
+[2607:ff28:800f:97:225:90ff:fe75:1110]:8333
[2620:11c:5001:1118:d267:e5ff:fee9:e673]:8333
-[2620:6e:a000:1:42:42:42:42]:8333
-[2804:14d:baa7:9674:21e:67ff:fea8:d799]:8333
-[2804:14d:baa7:9674:3615:9eff:fe23:d610]:8333
-[2804:39e8:ff85:a600:7285:c2ff:feae:9925]:8333
-[2804:d41:aa01:1600:5a2d:3b27:3b83:2b45]:8333
-[2a00:12d8:7001:1:46e7:6915:75be:92f9]:8333
+[2620:6e:a000:2001::6]:8333
+[2804:14d:4c93:9809:9769:da80:1832:3480]:8333
+[2a00:1328:e101:c00::163]:8333
[2a00:1398:4:2a03:215:5dff:fed6:1033]:8333
+[2a00:13a0:3015:1:85:14:79:26]:8333
[2a00:1630:14::101]:8333
[2a00:1768:2001:27::ef6a]:8333
[2a00:1828:a004:2::666]:8333
-[2a00:1838:36:142::ec73]:8333
+[2a00:1838:36:17::38cb]:8333
[2a00:1838:36:7d::d3c6]:8333
-[2a00:1f40:2::1126]:8333
-[2a00:23a8:41d0:5800:20c:29ff:fe0d:6a75]:8333
-[2a00:23c5:fd01:9f00:6317:7c02:788f:88ea]:8333
-[2a00:6020:13c2:3800:be6a:a1c8:c9e7:65ec]:8333
-[2a00:63c2:8:88::2]:8333
-[2a00:7143:3::227]:8333
-[2a00:7b80:452:2000::138]:8333
+[2a00:1c10:2:709:58f7:e0ff:fe24:a0ba]:22220
+[2a00:1c10:2:709::217]:22220
+[2a00:1f40:5001:100::31]:8333
+[2a00:6020:1395:1400:baf7:2d43:60b3:198b]:8333
+[2a00:7c80:0:10b::3faf]:8333
[2a00:8a60:e012:a00::21]:8333
+[2a00:ab00:603:84::3]:8333
+[2a00:bbe0:cc:0:62a4:4cff:fe23:7510]:8333
[2a00:ca8:a1f:3025:f949:e442:c940:13e8]:8333
-[2a00:d70:0:15:f816:3eff:fe73:d819]:8333
-[2a00:d880:5:331::3978]:8333
-[2a01:238:420f:9200:fa5a:1a4b:1e6a:fadf]:8333
+[2a00:d2a0:a:3d00:1cdf:38bb:a7d6:c251]:8333
+[2a00:d880:11::20e]:8333
+[2a00:ec0:7207:9100:5f8f:25dd:2574:3982]:8333
+[2a00:f820:433::36]:8333
+[2a01:138:a017:b018::42]:8333
[2a01:430:17:1::ffff:1153]:8333
-[2a01:488:66:1000:53a9:1573:0:1]:8333
-[2a01:4f8:120:80cc::2]:8433
-[2a01:5f0:beef:5:0:3:0:1]:52101
-[2a01:79c:cebc:a630:9dd8:ef55:8374:92a1]:8333
-[2a01:7a0:2:137a::11]:8333
+[2a01:490:16:301::2]:8333
+[2a01:4b00:807c:1b00:cda1:c6a:2bad:2418]:8333
+[2a01:4b00:80e7:5405::1]:8333
+[2a01:4f8:192:4212::2]:8433
[2a01:7a0:2:137c::3]:8333
-[2a01:7c8:aab6:db:5054:ff:feca:cfc8]:8333
-[2a01:8b81:6403:4700::1]:8333
-[2a01:cb00:7cd:b000:fa1f:bd1:fe0:62a6]:8333
-[2a01:cb00:d3d:7700:227:eff:fe28:c565]:8333
+[2a01:7a7:2:1467:ec4:7aff:fee2:5690]:8333
+[2a01:7c8:d002:10f:5054:ff:fe5c:dac7]:8333
+[2a01:7c8:d002:318:5054:ff:febe:cbb1]:8333
+[2a01:8740:1:ffc5::8c6a]:8333
+[2a01:cb00:f98:ca00:5054:ff:fed4:763d]:8333
+[2a01:cb14:cf6:bc00:21e5:f12e:32c8:145]:8333
+[2a01:d0:0:1c::245]:8333
[2a01:d0:bef2::12]:8333
-[2a01:d0:f34f:1:1f67:e250:6aeb:b9c4]:8333
-[2a01:e34:ee6b:2ab0:88c2:1c12:f4eb:c26c]:8333
-[2a01:e35:2fba:2e90:1:0:b:1]:8333
-[2a02:1205:505d:eb50:beae:c5ff:fe42:a973]:8333
-[2a02:120b:2c3f:a90:10dd:31ff:fe42:5079]:8333
-[2a02:130:300:1520:1::2]:8333
-[2a02:13b8:4000:1000:216:e6ff:fe92:8619]:8333
+[2a01:e35:2e40:6830:211:32ff:fea6:de3d]:8333
+[2a02:1205:c6aa:60c0:70d8:aaee:a82d:993c]:8333
+[2a02:169:502::614]:8333
[2a02:180:1:1::5b8f:538c]:8333
-[2a02:2168:8062:db00:96de:80ff:fea3:fd00]:8333
-[2a02:2770:5:0:21a:4aff:fe44:8370]:8333
-[2a02:2788:864:fb3:5b8a:c8f7:9fff:ae2d]:8333
-[2a02:2f0d:607:bc00:5e9a:d8ff:fe57:8bc5]:8333
-[2a02:348:9a:83b1::1]:8333
+[2a02:348:62:5ef7::1]:8333
[2a02:390:9000:0:218:7dff:fe10:be33]:8333
-[2a02:4780:8:6:2:354e:1256:7a04]:8333
-[2a02:578:4f07:24:76ad:cef7:93c1:b9b9]:8333
-[2a02:6d40:30f6:e901:89b8:bb58:25a:6050]:8333
-[2a02:750:7:c11:5054:ff:fe43:eb81]:8333
[2a02:7aa0:1619::adc:8de0]:8333
-[2a02:7b40:4f62:19ae::1]:8333
-[2a02:8108:95bf:eae3:211:32ff:fe8e:b5b8]:8333
-[2a02:e00:fff0:23f::1]:8333
-[2a02:e00:fff0:23f::a]:8333
-[2a03:1b20:1:f410:40::3e]:16463
+[2a02:7b40:b0df:8925::1]:8333
+[2a02:7b40:b905:37db::1]:8333
+[2a02:810d:8cbf:f3a8:96c6:91ff:fe17:ae1d]:8333
+[2a02:8389:1c0:9680:201:2eff:fe82:b3cc]:8333
+[2a02:a454:a516:1:517:928:7e0d:957c]:8333
+[2a02:af8:fab0:804:151:236:34:161]:8333
+[2a02:af8:fab0:808:85:234:145:132]:8333
+[2a02:e00:fff0:1e2::a]:8333
+[2a03:2260:3006:d:d307:5d1d:32ca:1fe8]:8333
[2a03:6000:870:0:46:23:87:218]:8333
[2a03:9da0:f6:1::2]:8333
+[2a03:c980:db:47::]:8333
[2a03:e2c0:1ce::2]:8333
-[2a04:2180:0:2::f2]:8333
-[2a04:2180:1:c:f000::15]:8333
-[2a04:52c0:101:97f::dcbe]:8333
+[2a04:3544:1000:1510:706c:abff:fe6c:501c]:8333
+[2a04:52c0:101:383::2a87]:8333
+[2a04:52c0:101:3fb::4c27]:8333
[2a04:ee41:83:50df:d908:f71d:2a86:b337]:8333
-[2a05:1700::100]:8333
-[2a05:fc87:4::2]:8333
-[2a05:fc87:4::7]:8333
-[2a07:5741:0:69d::1]:8333
-[2a07:5741:0:7cd::1]:8333
-[2a07:7200:ffff:c53f::e1:17]:8333
+[2a05:6d40:b94e:d100:225:90ff:fe0d:cfc2]:8333
+[2a05:e5c0:0:100:250:56ff:feb9:d6cb]:8333
+[2a05:fc87:1:6::2]:8333
+[2a05:fc87:4::8]:8333
+[2a07:5741:0:115d::1]:8333
+[2a07:a880:4601:1062:b4b4:bd2a:39d4:7acf]:51401
+[2a07:abc4::1:946]:8333
[2a07:b400:1:34c::2:1002]:8333
+[2a0a:8c41::b4]:8333
+[2a0a:c801:1:7::183]:8333
[2a0b:ae40:3:4a0a::15]:8333
-[2a0e:b780::55d1:f05b]:8333
+[2a0f:df00:0:254::46]:8333
+[2c0f:f598:5:1:1001::1]:8333
[2c0f:fce8:0:400:b7c::1]:8333
-2empatdfea6vwete.onion:8333
-34aqcwnnuiqh234f.onion:8333
-3gxqibajrtysyp5o.onion:8333
-3sami4tg4yhctjyc.onion:8333
-3w77hrilg6q64opl.onion:8333
-46xh2sbjsjiyl4fu.onion:8333
-4ee44qsamrjpywju.onion:8333
-4haplrtkprjqhm2j.onion:8333
-4u3y3zf2emynt6ui.onion:8333
-57dytizbai7o4kq7.onion:8333
-5guaeulc7xm4g2mm.onion:8334
-5mtvd4dk62ccdk4v.onion:8333
-5pmjz6mmikyabaw5.onion:8333
-6eurcxoqsa4qpiqq.onion:8333
-6ivvkeseojsmpby4.onion:8333
-6tlha6njtcuwpfa3.onion:8333
-6ymgbvnn6d5nfmv4.onion:8333
-72y2n5rary4mywkz.onion:8333
-7b75ub5dapphemit.onion:8333
-7xaqpr7exrtlnjbb.onion:8333
-a64haiqsl76l25gv.onion:8333
-ab7ftdfw6qhdx3re.onion:8333
-aiupgbtdqpmwfpuz.onion:8333
-akeg56rzkg7rsyyg.onion:8333
-akinbo7tlegsnsxn.onion:8333
-anem5aq4cr2zl7tz.onion:8333
-at3w5qisczgguije.onion:8333
-auo4zjsp44vydv6c.onion:8333
-bowg4prf63givea4.onion:8333
-cjuek22p4vv4hzbu.onion:8333
-cklaa2xdawrb75fg.onion:8333
-coxiru76nnfw3vdj.onion:8333
-cwq2fuc54mlp3ojc.onion:8333
-dganr7dffsacayml.onion:8333
-djbsspmvlc6ijiis.onion:8333
-dmfwov5ycnpvulij.onion:8333
-dp2ekfbxubpdfrt4.onion:8333
-dw2ufbybrgtzssts.onion:4333
-edkmfeaapvavhtku.onion:8333
-ejdoey3uay3cz7bs.onion:8333
-eladlvwflaahxomr.onion:8333
-ffhx6ttq7ejbodua.onion:8333
-hbnnzteon75un65y.onion:8333
-hcyxhownxdv7yybw.onion:8333
-hdfcxll2tqs2l4jc.onion:8333
-hdld2bxyvzy45ds4.onion:8333
-hlnnhn2xj2qffqjs.onion:8333
-hnqwmqikfmnkpdja.onion:8333
-hvmjovdasoin43wn.onion:8333
-hwzcbnenp6dsp6ow.onion:8333
-i5ellwzndjuke242.onion:8333
-iapvpwzs4gpbl6fk.onion:8885
-if7fsvgyqwowxkcn.onion:8333
-ilukzjazxlxrbuwy.onion:8333
-kswfyurnglm65u7b.onion:8333
-ldu2hbiorkvdymja.onion:8333
-lvvgedppmpigudhz.onion:8333
-mk3bnep5ubou7i44.onion:8333
-muhp42ytbwi6qf62.onion:8333
-n5khsbd6whw7ooip.onion:8333
-ndmbrjcvu2s6jcom.onion:8333
-nf4iypnyjwfpcjm7.onion:8333
-nkdw6ywzt3dqwxuf.onion:8333
-o4sl5na6jeqgi3l6.onion:8333
-opencubebqqx3buj.onion:8333
-ovbkvgdllk3xxeah.onion:8333
-pg2jeh62fkq3byps.onion:8333
-pkcgxf23ws3lwqvq.onion:8333
-qdtau72ifwauot6b.onion:8333
-qidnrqy2ozz3nzqq.onion:8333
-readybit5veyche6.onion:8333
-s2epxac7ovy36ruj.onion:8333
-satofxsc3xjadxsm.onion:8333
-sv5oitfnsmfoc3wu.onion:8333
-uftbw4zi5wlzcwho.onion:8333
-uz3pvdhie3372vxw.onion:8333
-v2x7gpj3shxfnl25.onion:8333
-vov46htt6gyixdmb.onion:8333
-wg3b3qxcwcrraq2o.onion:8333
-wgeecjm4w4ko66f7.onion:8333
-wmxc6ask4a5xyaxh.onion:8333
-wqrafn4zal3bbbhr.onion:8333
-xhi5x5qc44elydk4.onion:8333
-xk6bjlmgvwojvozj.onion:8333
-xmgr7fsmp7bgburk.onion:8333
-xocvz3dzyu2kzu6f.onion:8333
-xv7pt6etwxiygss6.onion:8444
-yumx7asj7feoozic.onion:8333
-zmaddsqelw2oywfb.onion:8444
+226eupdnaouu4h2v.onion:8333
+22h7b6f3caabqqsu.onion:8333
+23wdfqkzttmenvki.onion:8333
+23yi3frxymtwdgre.onion:8333
+2ajon3moyf4i2hbb.onion:8333
+2bfmlpk55hffpl6e.onion:8333
+2ckmbf6sglwydeth.onion:8333
+2hkusi5gcaautwqf.onion:8333
+2ivhmlbxbgnkcykl.onion:8333
+2mmxouhv6nebowkq.onion:8333
+2qsnv6exnuuiar7z.onion:8333
+2qudbhlnvqpli3sz.onion:8333
+2ujxdfovfyjpmdto.onion:8333
+2xdgeufrek3eumkw.onion:8333
+2xdzsruhsej4tsiw.onion:8333
+34ran2woq4easmss.onion:8333
+36q7khhej2lxd3wf.onion:8333
+373wjdspuo52utzq.onion:8333
+376klet5xqbrg2jv.onion:8333
+37kwd7fxop766l5k.onion:8333
+3e5t7hq4alt5tovx.onion:8333
+3gbxhebfhouuwgc3.onion:8333
+3hgbjze2nbwyuewf.onion:8333
+3iuuvrd2waha2cxo.onion:8333
+3jtxujdaiwh6iltu.onion:8333
+3l5eq2du7mvscj4a.onion:8333
+3nofngnqlqeehn7o.onion:8333
+3r44ddzjitznyahw.onion:8333
+3vtbuwmton7vq5qz.onion:8333
+46ohzttz4peki43g.onion:8333
+47fl3ivl4v56jstr.onion:8333
+47i6qrl2ijqcwlg6.onion:8333
+47uupgzcnrwahoto.onion:8333
+4c5cki37evofds6d.onion:8333
+4eq36jrx7xuytfpc.onion:8333
+4ewkdxvcg57adrni.onion:8333
+4flvgibnm2nld3na.onion:8333
+4iaontym47imawe4.onion:8333
+4jxz37oou5ag763c.onion:8333
+4mnkvj6ha73eqnbk.onion:8333
+4nnuyxm5k5tlyjq3.onion:8333
+4nz2yg4cnote3ej7.onion:8333
+4pozwh6564ygzddk.onion:8333
+4qgfb56rvpbmesx7.onion:8333
+4rsax23taqzwmimj.onion:8333
+4u5j5ay6rasowt4m.onion:8333
+4vorvtoyegh4zbvr.onion:8333
+52s4j5pldwlpzhtw.onion:8333
+5abpiiqfvekoejro.onion:8333
+5aydzxx6jyoz3nez.onion:8333
+5cxzdsrtok5dgo4a.onion:8333
+5eduikpudie3jyrf.onion:8333
+5epeafkmya4fv5d5.onion:8333
+5fyxlztic3t6notz.onion:8333
+5hd6eyew5ybnq6gb.onion:8333
+5jyfzhwksb6urrp2.onion:8333
+5nooqgct567ig57v.onion:8333
+5nsfm4nqqzzprjrp.onion:8333
+5oqstxspzhlgjef6.onion:8333
+5pzzmd4tfonrqzb2.onion:8333
+5sckmx4yucbnp4io.onion:8333
+5ue7worzbn6hon3e.onion:8333
+5wxhx2tozpovf6z3.onion:8333
+5xk3yun36e32e34i.onion:8333
+5zght2g7vcsapi65.onion:8333
+62dcdpvdolfzkdzl.onion:8333
+63bko2mhixnn2b7d.onion:8333
+67hjvfv6wictalm5.onion:8333
+6g6ko4klkf5atldi.onion:8333
+6k5zreexw4cadxi5.onion:8333
+6kf5ayhlpenywgas.onion:8333
+6maigxjvcet4pite.onion:8333
+6ressv4dvplb5ihh.onion:8333
+6rjex6gyuaui3c5e.onion:8333
+6skgnf43pphdvjua.onion:8333
+6stxaoduwisg5sqh.onion:8333
+6xqy4ts6bo6u5dgm.onion:8333
+7avnl3dqpgu23jva.onion:8333
+7ff4wk266no23txn.onion:8333
+7hipbuzfdcyzqkkg.onion:8333
+7sjmlzrthjlpfydk.onion:8333
+7tut3zt2akwrmw6x.onion:8333
+7uhsjzj6nx3dfnxt.onion:8333
+7wm4wso3wvatxnbt.onion:8333
+7ykmzuybwd2ptzg4.onion:8333
+a27bvhina4y23jxo.onion:8333
+a53vtdm7uiet5vdl.onion:8333
+a56572xjuofnt2dp.onion:8333
+abp25knifdsnc2rv.onion:8333
+aefx7ubzpal7clak.onion:8333
+ai5r2diozoe7rrdz.onion:8333
+aipupphit3enggpj.onion:8333
+algpjjygd3gtnmpp.onion:8333
+alihua7rhyc452hr.onion:8333
+am3gyyfynxzwyxhx.onion:8333
+ankozzfhl2r3uc6u.onion:8333
+at3twjlbtc2lqnq5.onion:8333
+avqobl72pmc64dyi.onion:8333
+awmdz2fs3b5h5ut5.onion:8333
+ayywpiy77butdjrj.onion:8333
+b2i3pj7c24cvprs7.onion:8333
+b4ilebyxcu6nttio.onion:8333
+b4vvkbqipcmkwp4v.onion:8333
+bddfqxps5ibd3ftw.onion:8333
+be5bgcpo4ooux5qy.onion:8333
+bgla4m6zetvtv7ls.onion:8333
+bh32gzw3nyckzqut.onion:8333
+bho4kodpehn7xr3x.onion:8333
+bitcoin4rlfa4wqx.onion:8333
+biw7s6jf6r2mf3cu.onion:8333
+bk7yp6epnmcllq72.onion:8333
+blcktrgve5vetjsk.onion:8333
+blwbp7gfdffdsx4g.onion:8333
+bnxn6qqc55gvn5op.onion:8333
+bp7o22lvcjawelvv.onion:8333
+bqqyqucgj4tchn64.onion:8333
+bvdzmutcqf7gzzn5.onion:8333
+c36zmegjkinftmtf.onion:8333
+c4fn62gnltlgrptv.onion:8333
+caael5yedviooqzk.onion:8333
+caq54ablfbrnumdd.onion:8333
+cernrmrk5zomzozn.onion:8333
+chri6itgjaagof4t.onion:8333
+cncwik3tnd2ejm5z.onion:8333
+cuyjqoziemcmwaxl.onion:8333
+cx7qa2gpqyp7pld5.onion:8333
+czp7wgaus4gvio72.onion:8333
+d2fn54rfyjdangi4.onion:8333
+d2sk45u6ca64yeqh.onion:8333
+d3aowmngvktsziae.onion:8333
+d5iu4aiz3y2kgcgj.onion:8333
+d6zbw2sxnxgj5sv3.onion:8333
+db5rd5e46t7mgini.onion:8333
+dci2gulorl44yj55.onion:8333
+ddpth2mwt3rsvoog.onion:8333
+dfrwza7fcecknnms.onion:8333
+djwhjfj4rh3oz3yj.onion:8333
+dkk5mmpe5jtjodk5.onion:8333
+doj3zgmsbzurmqgp.onion:8333
+dpce4f3rcqddzbx5.onion:8333
+drwo3vnxch5ozfbo.onion:8333
+duikkidxip3lyexn.onion:8333
+duqdliptc22i6hf5.onion:8333
+duyp4coh5d7nh3ud.onion:8333
+duz5two3z7c55lxj.onion:8333
+dvu6dlar6ezc6xen.onion:8333
+dy6zqs46ycleayyp.onion:8333
+dz2ydmj3yqrcm4r7.onion:8333
+e2b2a5suvdawzxud.onion:8333
+e33h57j2ewkkqsn5.onion:8333
+e5kjiay7pzj5qpzv.onion:8333
+e7iko42d2wzcmvy4.onion:8333
+ea6boh4kotq56ws5.onion:8333
+efdx6gc4s5ezyqeg.onion:8333
+efrpuuic6ukeyqcs.onion:8333
+egruc3bi3itru6gq.onion:8333
+erc6tjs2ucyadl23.onion:8333
+eue2n5sk5tktg5bv.onion:8333
+ezkr7stq4w7ohjrt.onion:8333
+f3nyyjba6kpxznhk.onion:8333
+faq73vj4pcs73thu.onion:8333
+fdvtlj3pscbxuh75.onion:8333
+fgdpxov4nzxvhcpv.onion:8333
+fisqq6vzk3m6t225.onion:8333
+fkgp3qwegacrd2bj.onion:8333
+fo3tdfwx27takqq5.onion:8333
+fqkxtchwypispkpv.onion:8333
+fqunuhlwvd7rq6d5.onion:8333
+frwt5mscpyhiuwpe.onion:8333
+fta4gfjiuv6f2le2.onion:8333
+fuoy2ipuqrqwe5cf.onion:8333
+fz6nsij6jiyuwlsc.onion:8333
+g3vlnaaaog5sgui5.onion:8333
+g44i6jwsutkwmspz.onion:8333
+g55t65d5ckjixcnw.onion:8333
+gajd6eyrl2qwkfmg.onion:8333
+gblue3hr53p4grx7.onion:8333
+gbpro5tzduiuff4v.onion:8333
+gc4l3tql32qhfgmi.onion:8333
+gcnlorvtpycuajc6.onion:8333
+gdsib2nk2eeoidgc.onion:8333
+ge5gm7c6w7yahpz7.onion:8333
+gegcteeep4cwftl5.onion:8333
+gfoyraudgv5qjdku.onion:8333
+ggpbuypmxgi26lc6.onion:8333
+ghqivye7cfckisnt.onion:8333
+girakxomne5fby64.onion:8333
+glz5gfk33tuug5ne.onion:8333
+gplatxoyg5nxl5rj.onion:8333
+gripl5xjwy2dcr6c.onion:8333
+gthhzlmqci22nxru.onion:8333
+gto2d64swosfmk6c.onion:8333
+guaciney52mgcbp2.onion:8333
+gwktgrmtwk6nv5sc.onion:8333
+gwoxnokdcwc7hy4p.onion:8333
+h333f4qnwe7mrymn.onion:8333
+h6a32n4blbwwyn4d.onion:8333
+hafwtrbooszoembm.onion:8333
+hbwhgsb3eeinnr6t.onion:8333
+hcv6foxh5mk7fhb5.onion:8333
+hd6hktcl6wamzlzm.onion:8333
+hda6msa4v4rt77gx.onion:8333
+hdgnxkuqsd6wjwwx.onion:8333
+hgh3azn3eesddvcg.onion:8333
+hhyxu6bwkjefejoz.onion:8333
+hizn6rmofsg3upmn.onion:8333
+hjqxxsy2osemfvev.onion:8333
+hkbp7mbgw6klls4s.onion:8333
+hlojuwiwbkoj4kdz.onion:8333
+hlzxsjr7ob3qzzqq.onion:8333
+hniuzplezebyhv7a.onion:8333
+hondewkj4s4rdcwf.onion:8333
+hql5nv6vhceid3bn.onion:8333
+hspjo7mqrre5gyxr.onion:8333
+hu64s2mdr3x7yxka.onion:8333
+hvwvq2swkqw3qvyo.onion:8333
+hwo2biyndrrvpl6f.onion:8333
+hzxj3dth3y2xt45o.onion:8333
+i3ufxuw3t7cxfdpq.onion:8333
+ia3n3q5u45gvpx7a.onion:8333
+icfgs3fctckd4yeo.onion:8333
+icpz6thqvdjcwlvb.onion:8333
+if32zo5u4mhdunfd.onion:8333
+ig4lguql6vxkbmmr.onion:8333
+ihhcr7fhczqdac4y.onion:8333
+ijm2tyxob7vkvazz.onion:8333
+ip3puuqghumfz5ww.onion:8333
+iq3ket72f3y2frpg.onion:8333
+iqagt5co4dt7h6hf.onion:8333
+iugw42ih6hprqr26.onion:8333
+ivf774v4t7k63i6d.onion:8333
+ivfacdf7cig2z2y2.onion:8333
+ivsxdwku5og2zj4l.onion:8333
+ixwgrhaklvu4g6o7.onion:8333
+iz56moo6mkp3g7xo.onion:8333
+j2cp5muw5j3lumcx.onion:8333
+j2lrkrwugldwewws.onion:8333
+j2qtmkd2dablssz4.onion:8333
+j5e2yuan57v2h5el.onion:8333
+j5jfrdthqt5g25xz.onion:8333
+j5lk2uv2bspfqxfk.onion:8333
+janvvzsmzcsj3fil.onion:8333
+jenn2tmyl3xxarmq.onion:8333
+jfoe5f2sczojfp32.onion:8333
+jgcgi6k2pxooi5q3.onion:8333
+jhana24s3dzkitzp.onion:8333
+jitgulb24mvfqrdg.onion:8333
+jjuvwbjfzljmn7t3.onion:8333
+jlcfomgr5xfexaif.onion:8333
+jlehs6ybb26qlnna.onion:8333
+jljzz4tmbqrxq3q5.onion:8333
+joc4oqceedkg77vf.onion:8333
+jr5y6njubcbv6g37.onion:8333
+jroaos6la4vieho4.onion:8333
+jsmphgkay7iihbkr.onion:8333
+jtksnokusbzms7wl.onion:8333
+ju5duo3r6p6diznc.onion:8333
+jw6zymxcnebahuuj.onion:8333
+jxalvhf7w7wevqzw.onion:8333
+jyzhe3ig44ickysb.onion:8333
+jze6ukn4idrh44eo.onion:8333
+k4glotlxnmttb6ct.onion:8333
+k7uy3iwmvguzygd2.onion:8333
+kl23ofag3ukb6hxl.onion:8333
+kokt2qr6d4pmyb2d.onion:8333
+kpalu3h5ydkoaivs.onion:8333
+krdpbdvtqw5c5lee.onion:8333
+kriw6kzjzarzgb3g.onion:8333
+krp2thcmwrpsoue6.onion:8333
+kvyvdwjwtae5mo77.onion:8333
+kyrxri5rbr6ipurs.onion:8333
+kz3oxg7745dxt62q.onion:8333
+l3w5fcki2wbro2qb.onion:8333
+l44bisuxhh7reb5q.onion:8333
+l565g523emjebusj.onion:8333
+l6w5kdeigwsgnf5t.onion:8333
+l7a4emryfxkjgmmb.onion:8333
+l7sloscjqqbifcsw.onion:8333
+laafjqvtog7djfl2.onion:8333
+lah676kxbgbgw3u2.onion:8333
+lbq2a7pnpmviw2qo.onion:8333
+lc4wnpql27vymi35.onion:8333
+ldoffbfpk3j6c7y7.onion:8333
+lehpmglkivobq2qo.onion:8333
+lgewpjz7ie7daqqr.onion:8333
+lgkvbvro67jomosw.onion:8333
+liw5z4ngic6b7vnv.onion:8333
+ljs7gwrmmza6q6ga.onion:8333
+lmvax3e6awaxvhqi.onion:8333
+lrz77dwf7yq4cgnt.onion:8333
+lva54pnbq2nsmjyr.onion:8333
+lxc2uphxyyxflhnf.onion:8333
+lyjybdr4hmj3bqab.onion:8333
+lz2zlnmyynwtgwf2.onion:8333
+m6hcnpikimyh37yp.onion:8333
+md635omjnrgheed3.onion:8333
+mdb3oupwf4f2qyjb.onion:8333
+me6d4esx7ohdnxne.onion:8333
+mecfkik5ci47wckj.onion:8333
+mfrvevn7w6rwsp4r.onion:8333
+mimuutlew5srtduk.onion:8333
+mnysk3izxvra3huv.onion:8333
+mqu6gqtrhm6xzwwh.onion:8333
+mwuc6vom4ngijtb3.onion:8333
+mxdtrjhe2yfsx3pg.onion:8333
+n4ibet4piscv22nj.onion:8333
+n6d46vbzx43bevlb.onion:8333
+n6t6kfgzlvozxhfm.onion:8333
+n7rrochwerf2qxze.onion:8333
+ncsdiqmnxhnnjbsz.onion:8333
+nitxw3ilffngpumv.onion:8333
+njlsvubildehluwr.onion:8333
+njslfsivyyhixbsp.onion:8333
+nkf5e6b7pl4jfd4a.onion:8333
+nkppsb3t3ducje6m.onion:8333
+nlfwyqksmeqe45zz.onion:8333
+nlyjmpcmpaz5b4aa.onion:8333
+nnmv7z65k65mcesr.onion:8333
+nrrfwdmrm3imuebn.onion:8333
+nrrmkgmulpgsbwlt.onion:8333
+nw4h7leckut7eapv.onion:8333
+nwky3wd3ihoidvb5.onion:8333
+ny4kkemmmqv4lptm.onion:8333
+o25wkcw7eorg2toi.onion:8333
+o2gumvbkw6pm45cf.onion:8333
+o4yjshdwlbshylqw.onion:8333
+ofx4qgw6lppnvtgv.onion:8333
+oketipl4gndqcaus.onion:8333
+oq5q4qrqijr2kpun.onion:8333
+oqw3mfoiobqcklxh.onion:8333
+orsy2v63ecrmdj55.onion:8333
+ot4tzmznyimmlszk.onion:8333
+owk6c2jfthwkyahe.onion:8333
+oy7ss3hm2okx4tun.onion:8333
+p2pc6wbaepvdi6ce.onion:8333
+p2x24gdhasmgcl5j.onion:8333
+p6couujr2ndhllv3.onion:8333
+pa7dw5bln5lqmu53.onion:8333
+pasmchtoooj2kchd.onion:8333
+pdapkkhk6pbcy2tj.onion:8333
+peh5ajouuw6mw4sr.onion:8333
+pkuuc5pwl5xygwhr.onion:8333
+pq4wjl7vg7tsfycc.onion:8333
+ptbwqhusps5qieql.onion:8333
+ptwpbwyj5lnyew2f.onion:8333
+pu7w3jfyrzp7sxsi.onion:8333
+pwylbyvfuc62hhvx.onion:8333
+q2fhnnyt5b2ayvce.onion:8333
+q3i3apuionbazmfe.onion:8333
+qd6fcpu3pvbf2y3x.onion:8333
+qfewv3y7a3p4i3bd.onion:8333
+qhytdttflhbc4rsh.onion:8333
+qkn35rb3x2gxbwq4.onion:8333
+qlvlexs7pwac2f4b.onion:8333
+qogcqirtuta6rlxg.onion:8333
+qrzqfxkhrmu5v5ro.onion:8333
+qsyjasq46b2syiys.onion:8333
+quu4b2zjbnr2ue4y.onion:8333
+quycfj2wenz6bfyd.onion:8333
+qvdy3cmocnlv5v7c.onion:8333
+qvwhpqygan2xky5h.onion:8333
+qyutwc26ullujafb.onion:8333
+r45qg2d6iwfdhqwl.onion:8333
+r4xudr6u4r5nyga4.onion:8333
+r6apa5ssujxbwd34.onion:8333
+r6z2gcsu37k3gaah.onion:8333
+rbrjgfcca6v5b7yo.onion:8333
+rcifxibawqt6rxzz.onion:8333
+rdo3xctk3zkzjvln.onion:8333
+rdvlepy6ghgpapzo.onion:8333
+recs3a27chv2lg65.onion:8333
+rfmbiy5vztvn6hyn.onion:8333
+rli5lbje4k77inzw.onion:8333
+roqwnmepcj453vfh.onion:8333
+rpbnx54qniivrmh3.onion:8333
+rsvvogqdlijp77hv.onion:8333
+rwm5d4hg3hc77kdt.onion:8333
+s3yelkvc5f5xeysw.onion:8333
+s6rx52hitmpp4lge.onion:8333
+sa6m3rvycipgemky.onion:8333
+savebeesmkivmfbo.onion:8333
+sbyjr5npk2mlmfw7.onion:8333
+serwj42jme5xhhmw.onion:8333
+sg4vmubv3djrzvuh.onion:8333
+shsgksluz6jkgp6g.onion:8333
+sjyzmwwu6diiit3r.onion:8333
+sk3en3reudg3sdg5.onion:8333
+skoifp4oj7l4osu5.onion:8333
+sle2caplkln33e7y.onion:8333
+smdd7q7gonajdmjq.onion:8333
+spmhuxjb2cd7leun.onion:8333
+srkgyv5edn2pa7il.onion:8333
+sslnjjhnmwllysv4.onion:8333
+su66ygras6rkdtnl.onion:8333
+sundvmbjrtgdfahx.onion:8333
+svd65k5jpal2p3lt.onion:8333
+svua5hiqluw7o2sw.onion:8333
+sxqjubmum4rmfgpu.onion:8333
+t245vi742ti3tnka.onion:8333
+t4fbovvgzpnimd2p.onion:8333
+t4l4wv3erkhpde2p.onion:8333
+t5qchwbr6u5v2agk.onion:8333
+t7jlaj6ggyx7s5vy.onion:8333
+ta6sjeqyb27f4n4a.onion:8333
+tav7utpw4pfy7j6k.onion:8333
+taxg5z2sxfm5c4d6.onion:8333
+tekwvnbodbzrlufs.onion:8333
+tg4uwrjmtr2jlbjy.onion:8333
+th4cjvffjtw6vomu.onion:8333
+th6fxymtwnfifqeu.onion:8333
+thtchhl25u26nglq.onion:8333
+tiiah7csuoklcvi6.onion:8333
+tk63x5fk3337z3ud.onion:8333
+tkgootat6cqn7vyy.onion:8333
+tnj565wwqz5wpjvs.onion:8333
+ts6qx37mmpu6nj5y.onion:8333
+ttjisvxydgbtp56f.onion:8333
+twn54v7ra2xjgd55.onion:8333
+txem5meug24g2ezd.onion:8333
+tyiunn36lmfcq5lr.onion:8333
+tyv56xs6g6ndzqux.onion:8333
+u47f3hxwq65sgs4o.onion:8333
+u4r7fnholrdwwlni.onion:8333
+u556ofb3myarafwn.onion:8333
+u5q3gbz4qpz4wvlr.onion:8333
+uakly3ydrevvpxwi.onion:8333
+ug6hapi4qtekzc7v.onion:8333
+ui553qotd6ron3rf.onion:8333
+uir7f3wltoka6bbb.onion:8333
+ukrjjhwodl44wmof.onion:8333
+ul5gm2ixy7kqdfwg.onion:8333
+undd7rsj4pen3wo4.onion:8333
+uorwpzfehtykrg43.onion:8333
+uovsp2yltnaojq6l.onion:8333
+usazmdcs32ny24dy.onion:8333
+usazs7glm7geyxkl.onion:8333
+uss2kedg7qkwgdr5.onion:8333
+utgyrvw75wv2nymi.onion:8333
+uzwacms7kyzhehbl.onion:8333
+v2kdcetvslmdfcwr.onion:8333
+v5lhnzzv6nngfg5d.onion:8333
+vc44gb4veppobrt3.onion:8333
+vfwyhju43wxhzvux.onion:8333
+vgujufk53lqyolio.onion:8333
+vheejqq2v5dkb4xr.onion:8333
+vj64edev4jnqfdsb.onion:8333
+vmai5uigezr2khkj.onion:8333
+vmuykd7sxbmi7w57.onion:8333
+vomeacttinx3mpml.onion:8333
+vpow2xofg3fwzsdq.onion:8333
+vsawli4l5ifxdzaw.onion:8333
+vunubqkfms7sifok.onion:8333
+vuombnevwul4bqsb.onion:8333
+vxcpvdng65aefz6t.onion:8333
+vyxoizdzavp3obau.onion:8333
+wbeon2ci7lfio6ay.onion:8333
+wbwevew62mgsrrdz.onion:8333
+wfaydlg6zyfzjcu5.onion:8333
+wfz56s5lyn5dysez.onion:8333
+wg3mq4ugyy2gx32b.onion:8333
+whky54bctkf2n4p3.onion:8333
+whmjanqoyzizzc4t.onion:8333
+wlhou2wxgqyi3x3f.onion:8333
+wlvkfrplfiioz22o.onion:8333
+x3ngb3va7dovuenw.onion:8333
+x57x62bmmnylvo7r.onion:8333
+xgvm57mhgv564dka.onion:8333
+xhs3glfwnwiumivn.onion:8333
+xje5fwvyfdue2u6k.onion:8333
+xlgubgyly2blvsg5.onion:8333
+xnlu3tvakngy7tkp.onion:8333
+xo5marilhuyo7but.onion:8333
+xsaaxihdygnwxrix.onion:8333
+xu5mlugdsmzfkvzh.onion:8333
+xvrxqcptqvieedb2.onion:8333
+xwzhrrygftq3q4w4.onion:8333
+y4swmsaxdcos2bnu.onion:8333
+y5tl4lqi365pplud.onion:8333
+y5wzeqyaets5na6t.onion:8333
+y73qk2mzkjkhoky7.onion:8333
+y7oz3ydnvib4xhbb.onion:8333
+yah7qgfqqrteoche.onion:8333
+yba4brm555denlt7.onion:8333
+ygeqkg4inplsace3.onion:8333
+yjhnfu75lazbi34h.onion:8333
+yjw7kqapxx5vggoj.onion:8333
+ym7inmovbrna4gco.onion:8333
+yq5cusnuokscy64z.onion:8333
+yrcaioqrqrdwokqt.onion:8333
+yrcr7pgjuazad254.onion:8333
+yrksvon3tmvoohdv.onion:8333
+ytpus4vx5w7j6wp2.onion:8333
+ytqcigk2hhdl45ho.onion:8333
+yxojl3xmjus3dik2.onion:8333
+yzdqdsqx4fdung6w.onion:8333
+z33nukt7ngik3cpe.onion:8333
+z3ywbadw46ndnxgh.onion:8333
+z6mbqq7llxlrn4kq.onion:8333
+zb3lrcksn4rzhzje.onion:8333
+ze7odp7pzarjplsr.onion:8333
+zgbmhtbja4fy2373.onion:8333
+zh7hvalcgvjpoaqm.onion:8333
+ziztvxehmj5mehpg.onion:8333
+zjii3yecdrmq73y3.onion:8333
+zkrwmgjuvsza6ye2.onion:8333
+zoz2aopwi3wfuqwg.onion:8333
+ztdcfnh46773bivu.onion:8333
+zuxhc6d3nwpgc4af.onion:8333
+zuytrfevzjcpizli.onion:8333
+zvq6dpt3i2ofdp3g.onion:8333
+zwwm6ga7u2hqe2sd.onion:8333
+zyqb4lenfspntj5m.onion:8333
diff --git a/contrib/signet/README.md b/contrib/signet/README.md
new file mode 100644
index 0000000000..c4aa5ae2f7
--- /dev/null
+++ b/contrib/signet/README.md
@@ -0,0 +1,19 @@
+Contents
+========
+This directory contains tools related to Signet, both for running a Signet yourself and for using one.
+
+getcoins.py
+===========
+
+A script to call a faucet to get Signet coins.
+
+Syntax: `getcoins.py [-h|--help] [-c|--cmd=<bitcoin-cli path>] [-f|--faucet=<faucet URL>] [-a|--addr=<signet bech32 address>] [-p|--password=<faucet password>] [--] [<bitcoin-cli args>]`
+
+* `--cmd` lets you customize the bitcoin-cli path. By default it will look for it in the PATH
+* `--faucet` lets you specify which faucet to use; the faucet is assumed to be compatible with https://github.com/kallewoof/bitcoin-faucet
+* `--addr` lets you specify a Signet address; by default, the address must be a bech32 address. This and `--cmd` above complement each other (i.e. you do not need `bitcoin-cli` if you use `--addr`)
+* `--password` lets you specify a faucet password; this is handy if you are in a classroom and set up your own faucet for your students; (above faucet does not limit by IP when password is enabled)
+
+If using the default network, invoking the script with no arguments should be sufficient under normal
+circumstances, but if multiple people are behind the same IP address, the faucet will by default only
+accept one claim per day. See `--password` above.
diff --git a/contrib/signet/getcoins.py b/contrib/signet/getcoins.py
new file mode 100755
index 0000000000..691f0bb1b6
--- /dev/null
+++ b/contrib/signet/getcoins.py
@@ -0,0 +1,36 @@
+#!/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.
+
+import argparse
+import subprocess
+import requests
+import sys
+
+parser = argparse.ArgumentParser(description='Script to get coins from a faucet.', epilog='You may need to start with double-dash (--) when providing bitcoin-cli arguments.')
+parser.add_argument('-c', '--cmd', dest='cmd', default='bitcoin-cli', help='bitcoin-cli command to use')
+parser.add_argument('-f', '--faucet', dest='faucet', default='https://signetfaucet.com/claim', help='URL of the faucet')
+parser.add_argument('-a', '--addr', dest='addr', default='', help='Bitcoin address to which the faucet should send')
+parser.add_argument('-p', '--password', dest='password', default='', help='Faucet password, if any')
+parser.add_argument('bitcoin_cli_args', nargs='*', help='Arguments to pass on to bitcoin-cli (default: -signet)')
+
+args = parser.parse_args()
+
+if args.addr == '':
+ if args.bitcoin_cli_args == []:
+ args.bitcoin_cli_args = ['-signet']
+ # get address for receiving coins
+ try:
+ args.addr = subprocess.check_output([args.cmd] + args.bitcoin_cli_args + ['getnewaddress', 'faucet', 'bech32']).strip()
+ except FileNotFoundError:
+ print('The binary', args.cmd, 'could not be found.')
+ exit()
+
+data = {'address': args.addr, 'password': args.password}
+try:
+ res = requests.post(args.faucet, data=data)
+except:
+ print('Unexpected error when contacting faucet:', sys.exc_info()[0])
+ exit()
+print(res.text)
diff --git a/contrib/testgen/gen_key_io_test_vectors.py b/contrib/testgen/gen_key_io_test_vectors.py
index a00acb1f41..49320d92e6 100755
--- a/contrib/testgen/gen_key_io_test_vectors.py
+++ b/contrib/testgen/gen_key_io_test_vectors.py
@@ -15,8 +15,7 @@ import os
from itertools import islice
from base58 import b58encode_chk, b58decode_chk, b58chars
import random
-from binascii import b2a_hex
-from segwit_addr import bech32_encode, decode, convertbits, CHARSET
+from segwit_addr import bech32_encode, decode_segwit_address, convertbits, CHARSET
# key types
PUBKEY_ADDRESS = 0
@@ -109,7 +108,7 @@ def is_valid(v):
def is_valid_bech32(v):
'''Check vector v for bech32 validity'''
for hrp in ['bc', 'tb', 'bcrt']:
- if decode(hrp, v) != (None, None):
+ if decode_segwit_address(hrp, v) != (None, None):
return True
return False
@@ -141,9 +140,7 @@ def gen_valid_vectors():
rv, payload = valid_vector_generator(template)
assert is_valid(rv)
metadata = {x: y for x, y in zip(metadata_keys,template[3]) if y is not None}
- hexrepr = b2a_hex(payload)
- if isinstance(hexrepr, bytes):
- hexrepr = hexrepr.decode('utf8')
+ hexrepr = payload.hex()
yield (rv, hexrepr, metadata)
def gen_invalid_base58_vector(template):
diff --git a/depends/README.md b/depends/README.md
index 869ebe12fd..bf8f829848 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -25,7 +25,7 @@ Common `host-platform-triplets` for cross compilation are:
- `i686-pc-linux-gnu` for Linux 32 bit
- `x86_64-pc-linux-gnu` for x86 Linux
- `x86_64-w64-mingw32` for Win64
-- `x86_64-apple-darwin16` for macOS
+- `x86_64-apple-darwin18` for macOS
- `arm-linux-gnueabihf` for Linux ARM 32 bit
- `aarch64-linux-gnu` for Linux ARM 64 bit
- `powerpc64-linux-gnu` for Linux POWER 64-bit (big endian)
@@ -105,6 +105,10 @@ The following can be set when running make: `make FOO=bar`
<dd>Don't download/build/cache SQLite</dd>
<dt>NO_UPNP</dt>
<dd>Don't download/build/cache packages needed for enabling upnp</dd>
+<dt>ALLOW_HOST_PACKAGES</dt>
+<dd>Packages that are missed in dependencies (due to `NO_*` option or
+build script logic) are searched for among the host system packages using
+`pkg-config`. It allows building with packages of other (newer) versions</dd>
<dt>MULTIPROCESS</dt>
<dd>build libmultiprocess (experimental, requires cmake)</dd>
<dt>DEBUG</dt>
diff --git a/depends/config.site.in b/depends/config.site.in
index 87a3379303..f4531830c8 100644
--- a/depends/config.site.in
+++ b/depends/config.site.in
@@ -1,4 +1,14 @@
-depends_prefix="`dirname ${ac_site_file}`/.."
+# shellcheck shell=sh disable=SC2034 # Many variables set will be used in
+ # ./configure but shellcheck doesn't know
+ # that, hence: disable=SC2034
+
+true # Dummy command because shellcheck treats all directives before first
+ # command as file-wide, and we only want to disable for one line.
+ #
+ # See: https://github.com/koalaman/shellcheck/wiki/Directive
+
+# shellcheck disable=SC2154
+depends_prefix="$(cd "$(dirname ${ac_site_file})/.." && pwd)"
cross_compiling=maybe
host_alias=@HOST@
@@ -50,7 +60,7 @@ if test x@host_os@ = xdarwin; then
fi
PATH=$depends_prefix/native/bin:$PATH
-PKG_CONFIG="`which pkg-config` --static"
+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
@@ -69,7 +79,7 @@ fi
if test -n "@CXX@" -a -z "${CXX}"; then
CXX="@CXX@"
fi
-PYTHONPATH=$depends_prefix/native/lib/python3/dist-packages:$PYTHONPATH
+PYTHONPATH="${depends_prefix}/native/lib/python3/dist-packages${PYTHONPATH:+${PATH_SEPARATOR}}${PYTHONPATH}"
if test -n "@AR@"; then
AR=@AR@
diff --git a/depends/funcs.mk b/depends/funcs.mk
index 58d882eb05..5697bd6f15 100644
--- a/depends/funcs.mk
+++ b/depends/funcs.mk
@@ -163,7 +163,9 @@ $(1)_cmake=env CC="$$($(1)_cc)" \
CXXFLAGS="$$($(1)_cppflags) $$($(1)_cxxflags)" \
LDFLAGS="$$($(1)_ldflags)" \
cmake -DCMAKE_INSTALL_PREFIX:PATH="$$($($(1)_type)_prefix)"
-ifneq ($($(1)_type),build)
+ifeq ($($(1)_type),build)
+$(1)_cmake += -DCMAKE_INSTALL_RPATH:PATH="$$($($(1)_type)_prefix)/lib"
+else
ifneq ($(host),$(build))
$(1)_cmake += -DCMAKE_SYSTEM_NAME=$($(host_os)_cmake_system)
$(1)_cmake += -DCMAKE_C_COMPILER_TARGET=$(host)
diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk
index 6099fd4c71..e9faeba336 100644
--- a/depends/hosts/darwin.mk
+++ b/depends/hosts/darwin.mk
@@ -1,4 +1,4 @@
-OSX_MIN_VERSION=10.12
+OSX_MIN_VERSION=10.14
OSX_SDK_VERSION=10.15.1
XCODE_VERSION=11.3.1
XCODE_BUILD_ID=11C505
diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk
index 06cf974f75..d45ac3d03f 100644
--- a/depends/packages/bdb.mk
+++ b/depends/packages/bdb.mk
@@ -10,7 +10,9 @@ define $(package)_set_vars
$(package)_config_opts=--disable-shared --enable-cxx --disable-replication --enable-option-checking
$(package)_config_opts_mingw32=--enable-mingw
$(package)_config_opts_linux=--with-pic
-$(package)_cxxflags=-std=c++11
+$(package)_config_opts_android=--with-pic
+$(package)_cflags+=-Wno-error=implicit-function-declaration
+$(package)_cxxflags=-std=c++17
$(package)_cppflags_mingw32=-DUNICODE -D_UNICODE
endef
diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk
index d8bce108b1..ff8a252db9 100644
--- a/depends/packages/boost.mk
+++ b/depends/packages/boost.mk
@@ -1,50 +1,45 @@
package=boost
-$(package)_version=1_70_0
-$(package)_download_path=https://dl.bintray.com/boostorg/release/1.70.0/source/
+$(package)_version=1_71_0
+$(package)_download_path=https://dl.bintray.com/boostorg/release/$(subst _,.,$($(package)_version))/source/
$(package)_file_name=boost_$($(package)_version).tar.bz2
-$(package)_sha256_hash=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778
-$(package)_patches=unused_var_in_process.patch
+$(package)_sha256_hash=d73a8da01e8bf8c7eda40b4c84915071a8c8a0df4a6734537ddde4a8580524ee
+$(package)_dependencies=native_b2
define $(package)_set_vars
$(package)_config_opts_release=variant=release
$(package)_config_opts_debug=variant=debug
$(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam
-$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1
+$(package)_config_opts+=threading=multi link=static -sNO_COMPRESSION=1
$(package)_config_opts_linux=target-os=linux threadapi=pthread runtime-link=shared
$(package)_config_opts_darwin=target-os=darwin runtime-link=shared
$(package)_config_opts_mingw32=target-os=windows binary-format=pe threadapi=win32 runtime-link=static
-$(package)_config_opts_x86_64_mingw32=address-model=64
-$(package)_config_opts_i686_mingw32=address-model=32
-$(package)_config_opts_i686_linux=address-model=32 architecture=x86
-$(package)_config_opts_i686_android=address-model=32
-$(package)_config_opts_aarch64_android=address-model=64
-$(package)_config_opts_x86_64_android=address-model=64
-$(package)_config_opts_armv7a_android=address-model=32
-$(package)_toolset_$(host_os)=gcc
-$(package)_toolset_darwin=clang
+$(package)_config_opts_x86_64=architecture=x86 address-model=64
+$(package)_config_opts_i686=architecture=x86 address-model=32
+$(package)_config_opts_aarch64=address-model=64
+$(package)_config_opts_armv7a=address-model=32
ifneq (,$(findstring clang,$($(package)_cxx)))
- $(package)_toolset_$(host_os)=clang
+$(package)_toolset_$(host_os)=clang
+else
+$(package)_toolset_$(host_os)=gcc
endif
-$(package)_archiver_$(host_os)=$($(package)_ar)
$(package)_config_libraries=filesystem,system,thread,test
-$(package)_cxxflags=-std=c++11 -fvisibility=hidden
+$(package)_cxxflags=-std=c++17 -fvisibility=hidden
$(package)_cxxflags_linux=-fPIC
$(package)_cxxflags_android=-fPIC
endef
define $(package)_preprocess_cmds
- patch -p1 < $($(package)_patch_dir)/unused_var_in_process.patch && \
- echo "using $($(package)_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$($(package)_archiver_$(host_os))\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam
+ echo "using $($(package)_toolset_$(host_os)) : : $($(package)_cxx) : <cflags>\"$($(package)_cflags)\" <cxxflags>\"$($(package)_cxxflags)\" <compileflags>\"$($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$($(package)_ar)\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam
endef
define $(package)_config_cmds
- ./bootstrap.sh --without-icu --with-libraries=$($(package)_config_libraries) --with-toolset=$($(package)_toolset_$(host_os))
+ ./bootstrap.sh --without-icu --with-libraries=$($(package)_config_libraries) --with-toolset=$($(package)_toolset_$(host_os)) --with-bjam=b2
endef
define $(package)_build_cmds
- ./b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) stage
+ b2 -d2 -j2 -d1 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) stage
endef
define $(package)_stage_cmds
- ./b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) install
+ b2 -d0 -j4 --prefix=$($(package)_staging_prefix_dir) $($(package)_config_opts) toolset=$($(package)_toolset_$(host_os)) install
endef
diff --git a/depends/packages/native_b2.mk b/depends/packages/native_b2.mk
new file mode 100644
index 0000000000..aaa37cdcfa
--- /dev/null
+++ b/depends/packages/native_b2.mk
@@ -0,0 +1,20 @@
+package=native_b2
+$(package)_version=$(boost_version)
+$(package)_download_path=$(boost_download_path)
+$(package)_file_name=$(boost_file_name)
+$(package)_sha256_hash=$(boost_sha256_hash)
+$(package)_build_subdir=tools/build/src/engine
+ifneq (,$(findstring clang,$($(package)_cxx)))
+$(package)_toolset_$(host_os)=clang
+else
+$(package)_toolset_$(host_os)=gcc
+endif
+
+define $(package)_build_cmds
+ CXX="$($(package)_cxx)" CXXFLAGS="$($(package)_cxxflags)" ./build.sh "$($(package)_toolset_$(host_os))"
+endef
+
+define $(package)_stage_cmds
+ mkdir -p "$($(package)_staging_prefix_dir)"/bin/ && \
+ cp b2 "$($(package)_staging_prefix_dir)"/bin/
+endef
diff --git a/depends/packages/native_biplist.mk b/depends/packages/native_biplist.mk
deleted file mode 100644
index c3054cbd1a..0000000000
--- a/depends/packages/native_biplist.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-package=native_biplist
-$(package)_version=1.0.3
-$(package)_download_path=https://bitbucket.org/wooster/biplist/downloads
-$(package)_file_name=biplist-$($(package)_version).tar.gz
-$(package)_sha256_hash=4c0549764c5fe50b28042ec21aa2e14fe1a2224e239a1dae77d9e7f3932aa4c6
-$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
-
-define $(package)_build_cmds
- python3 setup.py build
-endef
-
-define $(package)_stage_cmds
- mkdir -p $($(package)_install_libdir) && \
- python3 setup.py install --root=$($(package)_staging_dir) --prefix=$(build_prefix) --install-lib=$($(package)_install_libdir)
-endef
diff --git a/depends/packages/native_cdrkit.mk b/depends/packages/native_cdrkit.mk
deleted file mode 100644
index 7bdf2d7dfd..0000000000
--- a/depends/packages/native_cdrkit.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-package=native_cdrkit
-$(package)_version=1.1.11
-$(package)_download_path=https://distro.ibiblio.org/fatdog/source/600/c
-$(package)_file_name=cdrkit-$($(package)_version).tar.bz2
-$(package)_sha256_hash=b50d64c214a65b1a79afe3a964c691931a4233e2ba605d793eb85d0ac3652564
-$(package)_patches=cdrkit-deterministic.patch
-
-define $(package)_preprocess_cmds
- patch -p1 < $($(package)_patch_dir)/cdrkit-deterministic.patch
-endef
-
-# Starting with 10.1, GCC defaults to -fno-common, resulting in linking errors.
-# Pass -fcommon to retain the legacy behaviour.
-define $(package)_config_cmds
- $($(package)_cmake) -DCMAKE_C_FLAGS="$$($(1)_cflags) -fcommon"
-endef
-
-define $(package)_build_cmds
- $(MAKE) genisoimage
-endef
-
-define $(package)_stage_cmds
- $(MAKE) DESTDIR=$($(package)_staging_dir) -C genisoimage install
-endef
-
-define $(package)_postprocess_cmds
- rm bin/isovfy bin/isoinfo bin/isodump bin/isodebug bin/devdump
-endef
diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk
index f99b689ecd..44108925a4 100644
--- a/depends/packages/native_ds_store.mk
+++ b/depends/packages/native_ds_store.mk
@@ -1,10 +1,9 @@
package=native_ds_store
-$(package)_version=1.1.2
+$(package)_version=1.3.0
$(package)_download_path=https://github.com/al45tair/ds_store/archive/
$(package)_file_name=v$($(package)_version).tar.gz
-$(package)_sha256_hash=3b3ecb7bf0a5157f5b6010bc3af7c141fb0ad3527084e63336220d22744bc20c
+$(package)_sha256_hash=76b3280cd4e19e5179defa23fb594a9dd32643b0c80d774bd3108361d94fb46d
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
-$(package)_dependencies=native_biplist
define $(package)_build_cmds
python3 setup.py build
diff --git a/depends/packages/native_mac_alias.mk b/depends/packages/native_mac_alias.mk
index e60b99dccc..5fe027fb8a 100644
--- a/depends/packages/native_mac_alias.mk
+++ b/depends/packages/native_mac_alias.mk
@@ -1,8 +1,8 @@
package=native_mac_alias
-$(package)_version=2.0.7
+$(package)_version=2.1.1
$(package)_download_path=https://github.com/al45tair/mac_alias/archive/
$(package)_file_name=v$($(package)_version).tar.gz
-$(package)_sha256_hash=6f606d3b6bccd2112aeabf1a063f5b5ece87005a5d7e97c8faca23b916e88838
+$(package)_sha256_hash=c0ffceee14f7d04a6eb323fb7b8217dc3f373b346198d2ca42300a8362db7efa
$(package)_install_libdir=$(build_prefix)/lib/python3/dist-packages
define $(package)_build_cmds
diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk
index 4627acb521..d4fd23a47b 100644
--- a/depends/packages/packages.mk
+++ b/depends/packages/packages.mk
@@ -20,8 +20,10 @@ upnp_packages=miniupnpc
multiprocess_packages = libmultiprocess capnp
multiprocess_native_packages = native_libmultiprocess native_capnp
-darwin_native_packages = native_biplist native_ds_store native_mac_alias
+darwin_native_packages = native_ds_store native_mac_alias
+
+$(host_arch)_$(host_os)_native_packages += native_b2
ifneq ($(build_os),darwin)
-darwin_native_packages += native_cctools native_cdrkit native_libdmg-hfsplus
+darwin_native_packages += native_cctools native_libdmg-hfsplus
endif
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 083bc68d66..bf34835e1a 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -12,8 +12,8 @@ $(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch
$(package)_patches+= fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch
$(package)_patches+= fix_android_qmake_conf.patch fix_android_jni_static.patch dont_hardcode_pwd.patch
$(package)_patches+= freetype_back_compat.patch drop_lrelease_dependency.patch fix_powerpc_libpng.patch
+$(package)_patches+= fix_mingw_cross_compile.patch fix_qpainter_non_determinism.patch
-# Update OSX_QT_TRANSLATIONS when this is updated
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
$(package)_qttranslations_sha256_hash=fb5a47799754af73d3bf501fe513342cfe2fc37f64e80df5533f6110e804220c
@@ -25,9 +25,10 @@ $(package)_extra_sources += $($(package)_qttools_file_name)
define $(package)_set_vars
$(package)_config_opts_release = -release
+$(package)_config_opts_release += -silent
$(package)_config_opts_debug = -debug
$(package)_config_opts += -bindir $(build_prefix)/bin
-$(package)_config_opts += -c++std c++11
+$(package)_config_opts += -c++std c++1z
$(package)_config_opts += -confirm-license
$(package)_config_opts += -hostprefix $(build_prefix)
$(package)_config_opts += -no-compile-examples
@@ -68,7 +69,6 @@ $(package)_config_opts += -nomake examples
$(package)_config_opts += -nomake tests
$(package)_config_opts += -opensource
$(package)_config_opts += -optimized-tools
-$(package)_config_opts += -pch
$(package)_config_opts += -pkg-config
$(package)_config_opts += -prefix $(host_prefix)
$(package)_config_opts += -qt-libpng
@@ -76,7 +76,6 @@ $(package)_config_opts += -qt-pcre
$(package)_config_opts += -qt-harfbuzz
$(package)_config_opts += -system-zlib
$(package)_config_opts += -static
-$(package)_config_opts += -silent
$(package)_config_opts += -v
$(package)_config_opts += -no-feature-bearermanagement
$(package)_config_opts += -no-feature-colordialog
@@ -116,6 +115,7 @@ $(package)_config_opts += -no-feature-xml
$(package)_config_opts_darwin = -no-dbus
$(package)_config_opts_darwin += -no-opengl
+$(package)_config_opts_darwin += -pch
ifneq ($(build_os),darwin)
$(package)_config_opts_darwin += -xplatform macx-clang-linux
@@ -124,8 +124,12 @@ $(package)_config_opts_darwin += -device-option MAC_SDK_VERSION=$(OSX_SDK_VERSIO
$(package)_config_opts_darwin += -device-option CROSS_COMPILE="$(host)-"
$(package)_config_opts_darwin += -device-option MAC_MIN_VERSION=$(OSX_MIN_VERSION)
$(package)_config_opts_darwin += -device-option MAC_TARGET=$(host)
+$(package)_config_opts_darwin += -device-option XCODE_VERSION=$(XCODE_VERSION)
endif
+# for macOS on Apple Silicon (ARM) see https://bugreports.qt.io/browse/QTBUG-85279
+$(package)_config_opts_arm_darwin += -device-option QMAKE_APPLE_DEVICE_ARCHS=arm64
+
$(package)_config_opts_linux = -qt-xkbcommon-x11
$(package)_config_opts_linux += -qt-xcb
$(package)_config_opts_linux += -no-xcb-xlib
@@ -147,6 +151,7 @@ $(package)_config_opts_mingw32 = -no-opengl
$(package)_config_opts_mingw32 += -no-dbus
$(package)_config_opts_mingw32 += -xplatform win32-g++
$(package)_config_opts_mingw32 += -device-option CROSS_COMPILE="$(host)-"
+$(package)_config_opts_mingw32 += -pch
$(package)_config_opts_android = -xplatform android-clang
$(package)_config_opts_android += -android-sdk $(ANDROID_SDK)
@@ -162,6 +167,7 @@ $(package)_config_opts_android += -qt-freetype
$(package)_config_opts_android += -no-fontconfig
$(package)_config_opts_android += -L $(host_prefix)/lib
$(package)_config_opts_android += -I $(host_prefix)/include
+$(package)_config_opts_android += -pch
$(package)_config_opts_aarch64_android += -android-arch arm64-v8a
$(package)_config_opts_armv7a_android += -android-arch armeabi-v7a
@@ -192,33 +198,53 @@ define $(package)_extract_cmds
tar --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools
endef
+# Preprocessing steps work as follows:
+#
+# 1. Apply our patches to the extracted source. See each patch for more info.
+#
+# 2. Point to lrelease in qttools/bin/lrelease; otherwise Qt will look for it in
+# $(host)/native/bin/lrelease and not find it.
+#
+# 3. Create a macOS-Clang-Linux mkspec using our mac-qmake.conf.
+#
+# 4. 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.
+#
+# 5. Put our C, CXX and LD FLAGS into gcc-base.conf. Only used for non-host builds.
+#
+# 6. Do similar for the win32-g++ mkspec.
+#
+# 7. In clang.conf, swap out clang & clang++, for our compiler + flags. See #17466.
+#
+# 8. Adjust a regex in toolchain.prf, to accomodate Guix's usage of
+# CROSS_LIBRARY_PATH. See #15277.
define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/freetype_back_compat.patch && \
patch -p1 -i $($(package)_patch_dir)/fix_powerpc_libpng.patch && \
- sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
patch -p1 -i $($(package)_patch_dir)/drop_lrelease_dependency.patch && \
- patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch &&\
+ patch -p1 -i $($(package)_patch_dir)/dont_hardcode_pwd.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_configure_mac.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch && \
+ patch -p1 -i $($(package)_patch_dir)/xkb-default.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_riscv64_arch.patch && \
+ patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_mingw_cross_compile.patch && \
+ patch -p1 -i $($(package)_patch_dir)/fix_qpainter_non_determinism.patch &&\
+ sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
mkdir -p qtbase/mkspecs/macx-clang-linux &&\
- cp -f qtbase/mkspecs/macx-clang/Info.plist.lib qtbase/mkspecs/macx-clang-linux/ &&\
- cp -f qtbase/mkspecs/macx-clang/Info.plist.app 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 && \
- patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch &&\
- patch -p1 -i $($(package)_patch_dir)/fix_configure_mac.patch &&\
- patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch &&\
- patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch &&\
- patch -p1 -i $($(package)_patch_dir)/xkb-default.patch &&\
- patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch &&\
- patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch &&\
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 && \
- patch -p1 -i $($(package)_patch_dir)/fix_riscv64_arch.patch &&\
- patch -p1 -i $($(package)_patch_dir)/no-xlib.patch &&\
- echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf &&\
- echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf &&\
sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \
sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \
sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \
@@ -252,10 +278,7 @@ define $(package)_stage_cmds
$(MAKE) -C src INSTALL_ROOT=$($(package)_staging_dir) $(addsuffix -install_subtargets,$(addprefix sub-,$($(package)_qt_libs))) && cd .. && \
$(MAKE) -C qttools/src/linguist/lrelease INSTALL_ROOT=$($(package)_staging_dir) install_target && \
$(MAKE) -C qttools/src/linguist/lupdate INSTALL_ROOT=$($(package)_staging_dir) install_target && \
- $(MAKE) -C qttranslations INSTALL_ROOT=$($(package)_staging_dir) install_subtargets && \
- if `test -f qtbase/src/plugins/platforms/xcb/xcb-static/libxcb-static.a`; then \
- cp qtbase/src/plugins/platforms/xcb/xcb-static/libxcb-static.a $($(package)_staging_prefix_dir)/lib; \
- fi
+ $(MAKE) -C qttranslations INSTALL_ROOT=$($(package)_staging_dir) install_subtargets
endef
define $(package)_postprocess_cmds
diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk
index c93aa1a74d..3b7f3690a4 100644
--- a/depends/packages/zeromq.mk
+++ b/depends/packages/zeromq.mk
@@ -12,7 +12,7 @@ define $(package)_set_vars
$(package)_config_opts += --disable-Werror --disable-drafts --enable-option-checking
$(package)_config_opts_linux=--with-pic
$(package)_config_opts_android=--with-pic
- $(package)_cxxflags=-std=c++11
+ $(package)_cxxflags=-std=c++17
endef
define $(package)_preprocess_cmds
diff --git a/depends/patches/boost/unused_var_in_process.patch b/depends/patches/boost/unused_var_in_process.patch
deleted file mode 100644
index 722f7bb5ea..0000000000
--- a/depends/patches/boost/unused_var_in_process.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-commit dbd95cdaefdea95307d004f019a1c394cf9389f0
-Author: fanquake <fanquake@gmail.com>
-Date: Mon Aug 17 20:15:17 2020 +0800
-
- Remove unused variable in Boost Process
-
- This causes issues with our linters / CI.
-
- Can be removed once depends Boost is 1.71.0 or later.
-
-diff --git a/boost/process/detail/posix/wait_group.hpp b/boost/process/detail/posix/wait_group.hpp
-index 9dc249803..2502d9772 100644
---- a/boost/process/detail/posix/wait_group.hpp
-+++ b/boost/process/detail/posix/wait_group.hpp
-@@ -137,7 +137,6 @@ inline bool wait_until(
-
- do
- {
-- int ret_sig = 0;
- int status;
- if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
- && (WIFEXITED(status) || WIFSIGNALED(status)))
diff --git a/depends/patches/native_cdrkit/cdrkit-deterministic.patch b/depends/patches/native_cdrkit/cdrkit-deterministic.patch
deleted file mode 100644
index 8ab0993dc4..0000000000
--- a/depends/patches/native_cdrkit/cdrkit-deterministic.patch
+++ /dev/null
@@ -1,86 +0,0 @@
---- cdrkit-1.1.11.old/genisoimage/tree.c 2008-10-21 19:57:47.000000000 -0400
-+++ cdrkit-1.1.11/genisoimage/tree.c 2013-12-06 00:23:18.489622668 -0500
-@@ -1139,8 +1139,9 @@
- scan_directory_tree(struct directory *this_dir, char *path,
- struct directory_entry *de)
- {
-- DIR *current_dir;
-+ int current_file;
- char whole_path[PATH_MAX];
-+ struct dirent **d_list;
- struct dirent *d_entry;
- struct directory *parent;
- int dflag;
-@@ -1164,7 +1165,8 @@
- this_dir->dir_flags |= DIR_WAS_SCANNED;
-
- errno = 0; /* Paranoia */
-- current_dir = opendir(path);
-+ //current_dir = opendir(path);
-+ current_file = scandir(path, &d_list, NULL, alphasort);
- d_entry = NULL;
-
- /*
-@@ -1173,12 +1175,12 @@
- */
- old_path = path;
-
-- if (current_dir) {
-+ if (current_file >= 0) {
- errno = 0;
-- d_entry = readdir(current_dir);
-+ d_entry = d_list[0];
- }
-
-- if (!current_dir || !d_entry) {
-+ if (current_file < 0 || !d_entry) {
- int ret = 1;
-
- #ifdef USE_LIBSCHILY
-@@ -1191,8 +1193,8 @@
- de->isorec.flags[0] &= ~ISO_DIRECTORY;
- ret = 0;
- }
-- if (current_dir)
-- closedir(current_dir);
-+ if(d_list)
-+ free(d_list);
- return (ret);
- }
- #ifdef ABORT_DEEP_ISO_ONLY
-@@ -1208,7 +1210,7 @@
- errmsgno(EX_BAD, "use Rock Ridge extensions via -R or -r,\n");
- errmsgno(EX_BAD, "or allow deep ISO9660 directory nesting via -D.\n");
- }
-- closedir(current_dir);
-+ free(d_list);
- return (1);
- }
- #endif
-@@ -1250,13 +1252,13 @@
- * The first time through, skip this, since we already asked
- * for the first entry when we opened the directory.
- */
-- if (dflag)
-- d_entry = readdir(current_dir);
-+ if (dflag && current_file >= 0)
-+ d_entry = d_list[current_file];
- dflag++;
-
-- if (!d_entry)
-+ if (current_file < 0)
- break;
--
-+ current_file--;
- /* OK, got a valid entry */
-
- /* If we do not want all files, then pitch the backups. */
-@@ -1348,7 +1350,7 @@
- insert_file_entry(this_dir, whole_path, d_entry->d_name);
- #endif /* APPLE_HYB */
- }
-- closedir(current_dir);
-+ free(d_list);
-
- #ifdef APPLE_HYB
- /*
diff --git a/depends/patches/qt/fix_mingw_cross_compile.patch b/depends/patches/qt/fix_mingw_cross_compile.patch
new file mode 100644
index 0000000000..67f76f1d85
--- /dev/null
+++ b/depends/patches/qt/fix_mingw_cross_compile.patch
@@ -0,0 +1,25 @@
+commit 5a992a549adfe5a587bbcd6cd2b2cee47d236e27
+Author: fanquake <fanquake@gmail.com>
+Date: Fri Sep 4 08:13:44 2020 +0800
+
+ Work around broken mingw cross-compilation
+
+ See upstream issues:
+ https://bugreports.qt.io/browse/QTBUG-63637
+ https://bugreports.qt.io/browse/QTBUG-63659
+ https://codereview.qt-project.org/q/8bebded9
+
+ We should be able to drop this once we are building qt 5.10.1 or later.
+
+ Added in #12971.
+
+diff --git a/qtbase/mkspecs/win32-g++/qmake.conf b/qtbase/mkspecs/win32-g++/qmake.conf
+index e071a0d1..ad229b10 100644
+--- a/qtbase/mkspecs/win32-g++/qmake.conf
++++ b/qtbase/mkspecs/win32-g++/qmake.conf
+@@ -87,3 +87,5 @@ QMAKE_NM = $${CROSS_COMPILE}nm -P
+ include(../common/angle.conf)
+
+ load(qt_config)
++QMAKE_LINK_OBJECT_MAX = 10
++QMAKE_LINK_OBJECT_SCRIPT = object_script
diff --git a/depends/patches/qt/fix_qpainter_non_determinism.patch b/depends/patches/qt/fix_qpainter_non_determinism.patch
new file mode 100644
index 0000000000..3cfcc22f03
--- /dev/null
+++ b/depends/patches/qt/fix_qpainter_non_determinism.patch
@@ -0,0 +1,63 @@
+commit 2a8f7dc6ddfc414a66491522501c1574a1343ee1
+Author: Andrew Chow <achow101-github@achow101.com>
+Date: Sat Nov 21 01:11:04 2020 -0500
+
+ build: Fix determinism issue when building with Clang 8
+
+ When building Qt with LLVM/Clang 8 under -O3 (the default), we run into
+ a determinism issue in `qt_interset_spans`. The issue has been fixed for
+ LLVM/Clang 9, see
+ https://github.com/llvm/llvm-project/commit/db101864bdc938deb1d63fe4f7da761bd38e5cae
+ and https://reviews.llvm.org/D64601, however this fix was not backported
+ to 8.x. Once LLVM/Clang 9 is used, this patch can be dropped.
+
+ The particular issue appears to be an optimization done by -O3 which
+ adds a temporary variable for `spans->y` in `qt_intersect_spans`. When
+ it does this, sometimes it chooses to use a 32-bit movs instruction
+ (movswl), and other times it chooses a 64-bit movs instruction (movswq).
+ By patching `qt_intersect_spans` to always make a temporary variable for
+ `spans->y`, we are able to sidestep this problem.
+
+diff --git a/qtbase/src/gui/painting/qpaintengine_raster.cpp b/qtbase/src/gui/painting/qpaintengine_raster.cpp
+index 92ab6e8375..f018009e0b 100644
+--- a/qtbase/src/gui/painting/qpaintengine_raster.cpp
++++ b/qtbase/src/gui/painting/qpaintengine_raster.cpp
+@@ -3971,22 +3971,23 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip,
+ const QSpan *clipEnd = clip->m_spans + clip->count;
+
+ while (available && spans < end ) {
++ const short spans_y = spans->y;
+ if (clipSpans >= clipEnd) {
+ spans = end;
+ break;
+ }
+- if (clipSpans->y > spans->y) {
++ if (clipSpans->y > spans_y) {
+ ++spans;
+ continue;
+ }
+- if (spans->y != clipSpans->y) {
+- if (spans->y < clip->count && clip->m_clipLines[spans->y].spans)
+- clipSpans = clip->m_clipLines[spans->y].spans;
++ if (spans_y != clipSpans->y) {
++ if (spans_y < clip->count && clip->m_clipLines[spans_y].spans)
++ clipSpans = clip->m_clipLines[spans_y].spans;
+ else
+ ++clipSpans;
+ continue;
+ }
+- Q_ASSERT(spans->y == clipSpans->y);
++ Q_ASSERT(spans_y == clipSpans->y);
+
+ int sx1 = spans->x;
+ int sx2 = sx1 + spans->len;
+@@ -4005,7 +4006,7 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip,
+ if (len) {
+ out->x = qMax(sx1, cx1);
+ out->len = qMin(sx2, cx2) - out->x;
+- out->y = spans->y;
++ out->y = spans_y;
+ out->coverage = qt_div_255(spans->coverage * clipSpans->coverage);
+ ++out;
+ --available;
+
diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf
index 4cd96df29f..0142667547 100644
--- a/depends/patches/qt/mac-qmake.conf
+++ b/depends/patches/qt/mac-qmake.conf
@@ -1,12 +1,12 @@
MAKEFILE_GENERATOR = UNIX
-CONFIG += app_bundle incremental global_init_link_order lib_version_first plugin_no_soname absolute_library_soname
+CONFIG += app_bundle incremental lib_version_first absolute_library_soname
QMAKE_INCREMENTAL_STYLE = sublib
include(../common/macx.conf)
include(../common/gcc-base-mac.conf)
include(../common/clang.conf)
include(../common/clang-mac.conf)
QMAKE_MAC_SDK_PATH=$${MAC_SDK_PATH}
-QMAKE_XCODE_VERSION=4.3
+QMAKE_XCODE_VERSION = $${XCODE_VERSION}
QMAKE_XCODE_DEVELOPER_PATH=/Developer
QMAKE_MACOSX_DEPLOYMENT_TARGET = $${MAC_MIN_VERSION}
QMAKE_MAC_SDK=macosx
diff --git a/doc/JSON-RPC-interface.md b/doc/JSON-RPC-interface.md
index 40d8e330e2..c66e79af71 100644
--- a/doc/JSON-RPC-interface.md
+++ b/doc/JSON-RPC-interface.md
@@ -127,3 +127,14 @@ However, the wallet may not be up-to-date with the current state of the mempool
or the state of the mempool by an RPC that returned before this RPC. For
example, a wallet transaction that was BIP-125-replaced in the mempool prior to
this RPC may not yet be reflected as such in this RPC response.
+
+## Limitations
+
+There is a known issue in the JSON-RPC interface that can cause a node to crash if
+too many http connections are being opened at the same time because the system runs
+out of available file descriptors. To prevent this from happening you might
+want to increase the number of maximum allowed file descriptors in your system
+and try to prevent opening too many connections to your JSON-RPC interface at the
+same time if this is under your control. It is hard to give general advice
+since this depends on your system but if you make several hundred requests at
+once you are definitely at risk of encountering this issue.
diff --git a/doc/REST-interface.md b/doc/REST-interface.md
index 842a3964df..3b127703b7 100644
--- a/doc/REST-interface.md
+++ b/doc/REST-interface.md
@@ -12,6 +12,18 @@ REST Interface consistency guarantees
The [same guarantees as for the RPC Interface](/doc/JSON-RPC-interface.md#rpc-consistency-guarantees)
apply.
+Limitations
+-----------
+
+There is a known issue in the REST interface that can cause a node to crash if
+too many http connections are being opened at the same time because the system runs
+out of available file descriptors. To prevent this from happening you might
+want to increase the number of maximum allowed file descriptors in your system
+and try to prevent opening too many connections to your rest interface at the
+same time if this is under your control. It is hard to give general advice
+since this depends on your system but if you make several hundred requests at
+once you are definitely at risk of encountering this issue.
+
Supported API
-------------
diff --git a/doc/bips.md b/doc/bips.md
index ad6f7a0767..8c20533c9b 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -45,3 +45,4 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.21.0**):
* [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)).
* [`BIP 325`](https://github.com/bitcoin/bips/blob/master/bip-0325.mediawiki): Signet test network is supported as of **v0.21.0** ([PR 18267](https://github.com/bitcoin/bitcoin/pull/18267)).
* [`BIP 339`](https://github.com/bitcoin/bips/blob/master/bip-0339.mediawiki): Relay of transactions by wtxid is supported as of **v0.21.0** ([PR 18044](https://github.com/bitcoin/bitcoin/pull/18044)).
+* [`BIP 340`](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) [`341`](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) [`342`](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki): Validation rules for Taproot (including Schnorr signatures and Tapscript leaves) are implemented as of **v0.21.0** ([PR 19953](https://github.com/bitcoin/bitcoin/pull/19953)), without mainnet activation.
diff --git a/doc/build-freebsd.md b/doc/build-freebsd.md
index f48855a344..18ea84c579 100644
--- a/doc/build-freebsd.md
+++ b/doc/build-freebsd.md
@@ -1,59 +1,127 @@
-FreeBSD build guide
-======================
-(updated for FreeBSD 12.0)
+# FreeBSD Build Guide
-This guide describes how to build bitcoind and command-line utilities on FreeBSD.
+**Updated for FreeBSD [12.2](https://www.freebsd.org/releases/12.2R/announce.html)**
-This guide does not contain instructions for building the GUI.
+This guide describes how to build bitcoind, command-line utilities, and GUI on FreeBSD.
+
+## Dependencies
+
+The following dependencies are **required**:
+
+ Library | Purpose | Description
+ ----------------------------------------------------------------------|------------|----------------------
+ [autoconf](https://svnweb.freebsd.org/ports/head/devel/autoconf/) | Build | Automatically configure software source code
+ [automake](https://svnweb.freebsd.org/ports/head/devel/automake/) | Build | Generate makefile (requires autoconf)
+ [libtool](https://svnweb.freebsd.org/ports/head/devel/libtool/) | Build | Shared library support
+ [pkgconf](https://svnweb.freebsd.org/ports/head/devel/pkgconf/) | Build | Configure compiler and linker flags
+ [git](https://svnweb.freebsd.org/ports/head/devel/git/) | Clone | Version control system
+ [gmake](https://svnweb.freebsd.org/ports/head/devel/gmake/) | Compile | Generate executables
+ [boost-libs](https://svnweb.freebsd.org/ports/head/devel/boost-libs/) | Utility | Library for threading, data structures, etc
+ [libevent](https://svnweb.freebsd.org/ports/head/devel/libevent/) | Networking | OS independent asynchronous networking
+
+
+The following dependencies are **optional**:
+
+ Library | Purpose | Description
+ ---------------------------------------------------------------------------|------------------|----------------------
+ [db5](https://svnweb.freebsd.org/ports/head/databases/db5/) | Berkeley DB | Wallet storage (only needed when wallet enabled)
+ [qt5](https://svnweb.freebsd.org/ports/head/devel/qt5/) | GUI | GUI toolkit (only needed when GUI enabled)
+ [libqrencode](https://svnweb.freebsd.org/ports/head/graphics/libqrencode/) | QR codes in GUI | Generating QR codes (only needed when GUI enabled)
+ [libzmq4](https://svnweb.freebsd.org/ports/head/net/libzmq4/) | ZMQ notification | Allows generating ZMQ notifications (requires ZMQ version >= 4.0.0)
+ [sqlite3](https://svnweb.freebsd.org/ports/head/databases/sqlite3/) | SQLite DB | Wallet storage (only needed when wallet enabled)
+ [python3](https://svnweb.freebsd.org/ports/head/lang/python3/) | Testing | Python Interpreter (only needed when running the test suite)
+
+ See [dependencies.md](dependencies.md) for a complete overview.
## Preparation
-You will need the following dependencies, which can be installed as root via pkg:
+### 1. Install Required Dependencies
+Install the required dependencies the usual way you [install software on FreeBSD](https://www.freebsd.org/doc/en/books/handbook/ports.html) - either with `pkg` or via the Ports collection. The example commands below use `pkg` which is usually run as `root` or via `sudo`. If you want to use `sudo`, and you haven't set it up: [use this guide](http://www.freebsdwiki.net/index.php/Sudo%2C_configuring) to setup `sudo` access on FreeBSD.
```bash
pkg install autoconf automake boost-libs git gmake libevent libtool pkgconf
+```
+
+### 2. Clone Bitcoin Repo
+Now that `git` and all the required dependencies are installed, let's clone the Bitcoin Core repository to a directory. All build scripts and commands will run from this directory.
+``` bash
git clone https://github.com/bitcoin/bitcoin.git
```
-In order to run the test suite (recommended), you will need to have Python 3 installed:
+### 3. Install Optional Dependencies
+
+#### Wallet Dependencies
+It is not necessary to build wallet functionality to run bitcoind or the GUI. To enable legacy wallets, you must install `db5`. To enable [descriptor wallets](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md), `sqlite3` is required. Skip `db5` if you intend to *exclusively* use descriptor wallets
+
+###### Legacy Wallet Support
+`db5` is required to enable support for legacy wallets. Skip if you don't intend to use legacy wallets
```bash
-pkg install python3
+pkg install db5
```
-See [dependencies.md](dependencies.md) for a complete overview.
+###### Descriptor Wallet Support
-### Building BerkeleyDB
+`sqlite3` is required to enable support for descriptor wallets. Skip if you don't intend to use descriptor wallets.
+``` bash
+pkg install sqlite3
+```
+---
-BerkeleyDB is only necessary for the wallet functionality. To skip this, pass
-`--disable-wallet` to `./configure` and skip to the next section.
+#### GUI Dependencies
+###### Qt5
+Bitcoin Core includes a GUI built with the cross-platform Qt Framework. To compile the GUI, we need to install `qt5`. Skip if you don't intend to use the GUI.
```bash
-./contrib/install_db4.sh `pwd`
-export BDB_PREFIX="$PWD/db4"
+pkg install qt5
```
+###### libqrencode
+
+The GUI can encode addresses in a QR Code. To build in QR support for the GUI, install `libqrencode`. Skip if not using the GUI or don't want QR code functionality.
+```bash
+pkg install libqrencode
+```
+---
+
+#### 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
+pkg install python3
+```
+---
## Building Bitcoin Core
-**Important**: Use `gmake` (the non-GNU `make` will exit with an error).
+### 1. Configuration
-With wallet:
+There are many ways to configure Bitcoin Core, here are a few common examples:
+##### Wallet (BDB + SQlite) Support, No GUI:
+This explicitly enables legacy wallet support and disables the GUI. If `sqlite3` is installed, then descriptor wallet support will be built.
```bash
./autogen.sh
-./configure --with-gui=no \
- BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx-4.8" \
- BDB_CFLAGS="-I${BDB_PREFIX}/include" \
+./configure --with-gui=no --with-incompatible-bdb \
+ BDB_LIBS="-ldb_cxx-5" \
+ BDB_CFLAGS="-I/usr/local/include/db5" \
MAKE=gmake
```
-Without wallet:
+##### Wallet (only SQlite) and GUI Support:
+This explicitly enables the GUI and disables legacy wallet support. If `qt5` is not installed, this will throw an error. If `sqlite3` is installed then descriptor wallet functionality will be built. If `sqlite3` is not installed, then wallet functionality will be disabled.
```bash
./autogen.sh
-./configure --with-gui=no --disable-wallet MAKE=gmake
+./configure --without-bdb --with-gui=yes MAKE=gmake
+```
+##### No Wallet or GUI
+``` bash
+./autogen.sh
+./configure --without-wallet --with-gui=no MAKE=gmake
```
-followed by:
+### 2. Compile
+**Important**: Use `gmake` (the non-GNU `make` will exit with an error).
```bash
gmake # use -jX here for parallelism
diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md
index 2b051c078c..dccd7b1335 100644
--- a/doc/build-openbsd.md
+++ b/doc/build-openbsd.md
@@ -15,6 +15,7 @@ pkg_add qt5 # (optional for enabling the GUI)
pkg_add autoconf # (select highest version, e.g. 2.69)
pkg_add automake # (select highest version, e.g. 1.16)
pkg_add python # (select highest version, e.g. 3.8)
+pkg_add bash
git clone https://github.com/bitcoin/bitcoin.git
```
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 2a7d71eea6..c1d101fde1 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -19,7 +19,7 @@ Then install [Homebrew](https://brew.sh).
## Dependencies
```shell
-brew install automake berkeley-db4 libtool boost miniupnpc pkg-config python qt libevent qrencode sqlite
+brew install automake libtool boost miniupnpc pkg-config python qt libevent qrencode
```
If you run into issues, check [Homebrew's troubleshooting page](https://docs.brew.sh/Troubleshooting).
@@ -30,7 +30,22 @@ If you want to build the disk image with `make deploy` (.dmg / optional), you ne
brew install librsvg
```
-## Berkeley DB
+The wallet support requires one or both of the dependencies ([*SQLite*](#sqlite) and [*Berkeley DB*](#berkeley-db)) in the sections below.
+To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode).
+
+#### SQLite
+
+Usually, macOS installation already has a suitable SQLite installation.
+Also, the Homebrew package could be installed:
+
+```shell
+brew install sqlite
+```
+
+In that case the Homebrew package will prevail.
+
+#### Berkeley DB
+
It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
you can use [this](/contrib/install_db4.sh) script to install it
like so:
@@ -41,7 +56,11 @@ like so:
from the root of the repository.
-**Note**: You only need Berkeley DB if the wallet is enabled (see [*Disable-wallet mode*](/doc/build-osx.md#disable-wallet-mode)).
+Also, the Homebrew package could be installed:
+
+```shell
+brew install berkeley-db4
+```
## Build Bitcoin Core
@@ -72,14 +91,14 @@ from the root of the repository.
make deploy
```
-## `disable-wallet` mode
+## Disable-wallet mode
When the intention is to run only a P2P node without a wallet, Bitcoin Core may be
-compiled in `disable-wallet` mode with:
+compiled in disable-wallet mode with:
```shell
./configure --disable-wallet
```
-In this case there is no dependency on Berkeley DB 4.8 and SQLite.
+In this case there is no dependency on [*Berkeley DB*](#berkeley-db) and [*SQLite*](#sqlite).
Mining is also possible in disable-wallet mode using the `getblocktemplate` RPC call.
@@ -111,6 +130,6 @@ tail -f $HOME/Library/Application\ Support/Bitcoin/debug.log
```
## Notes
-* Tested on OS X 10.12 Sierra through macOS 10.15 Catalina on 64-bit Intel
+* Tested on OS X 10.14 Mojave through macOS 11 Big Sur on 64-bit Intel
processors only.
* Building with downloaded Qt binaries 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 c076fb6fff..cfe3328b45 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -41,12 +41,12 @@ Optional dependencies:
Library | Purpose | Description
------------|------------------|----------------------
miniupnpc | UPnP Support | Firewall-jumping support
- libdb4.8 | Berkeley DB | Wallet storage (only needed when wallet enabled)
+ libdb4.8 | Berkeley DB | Optional, wallet storage (only needed when wallet enabled)
qt | GUI | GUI toolkit (only needed when GUI enabled)
libqrencode | QR codes in GUI | Optional for generating QR codes (only needed when GUI enabled)
univalue | Utility | JSON parsing and encoding (bundled version will be used unless --with-system-univalue passed to configure)
libzmq3 | ZMQ notification | Optional, allows generating ZMQ notifications (requires ZMQ version >= 4.0.0)
- sqlite3 | SQLite DB | Wallet storage (only needed when wallet enabled)
+ sqlite3 | SQLite DB | Optional, wallet storage (only needed when wallet enabled)
For the versions used, see [dependencies.md](dependencies.md)
diff --git a/doc/dependencies.md b/doc/dependencies.md
index ddd50ef296..76e8910871 100644
--- a/doc/dependencies.md
+++ b/doc/dependencies.md
@@ -6,19 +6,19 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct
| Dependency | Version used | Minimum required | CVEs | Shared | [Bundled Qt library](https://doc.qt.io/qt-5/configure-options.html#third-party-libraries) |
| --- | --- | --- | --- | --- | --- |
| Berkeley DB | [4.8.30](https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html) | 4.8.x | No | | |
-| Boost | [1.70.0](https://www.boost.org/users/download/) | [1.58.0](https://github.com/bitcoin/bitcoin/pull/19667) | No | | |
-| Clang | | [3.3+](https://releases.llvm.org/download.html) (C++11 support) | | | |
+| Boost | [1.71.0](https://www.boost.org/users/download/) | [1.58.0](https://github.com/bitcoin/bitcoin/pull/19667) | No | | |
+| Clang | | [5.0+](https://releases.llvm.org/download.html) (C++17 support) | | | |
| Expat | [2.2.7](https://libexpat.github.io/) | | No | Yes | |
| fontconfig | [2.12.1](https://www.freedesktop.org/software/fontconfig/release/) | | No | Yes | |
| FreeType | [2.7.1](https://download.savannah.gnu.org/releases/freetype) | | No | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) (Android only) |
-| GCC | | [4.8+](https://gcc.gnu.org/) (C++11 support) | | | |
+| GCC | | [7+](https://gcc.gnu.org/) (C++17 support) | | | |
| HarfBuzz-NG | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| libevent | [2.1.11-stable](https://github.com/libevent/libevent/releases) | [2.0.21](https://github.com/bitcoin/bitcoin/pull/18676) | No | | |
| libpng | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
| librsvg | | | | | |
| MiniUPnPc | [2.0.20180203](https://miniupnp.tuxfamily.org/files) | | No | | |
| PCRE | | | | | [Yes](https://github.com/bitcoin/bitcoin/blob/master/depends/packages/qt.mk) |
-| Python (tests) | | [3.5](https://www.python.org/downloads) | | | |
+| Python (tests) | | [3.6](https://www.python.org/downloads) | | | |
| qrencode | [3.4.4](https://fukuchi.org/works/qrencode) | | No | | |
| Qt | [5.9.8](https://download.qt.io/official_releases/qt/) | [5.5.1](https://github.com/bitcoin/bitcoin/issues/13478) | No | | |
| SQLite | [3.32.1](https://sqlite.org/download.html) | [3.7.17](https://github.com/bitcoin/bitcoin/pull/19077) | | | |
@@ -33,8 +33,8 @@ Some dependencies are not needed in all configurations. The following are some f
#### Options passed to `./configure`
* MiniUPnPc is not needed with `--with-miniupnpc=no`.
-* Berkeley DB is not needed with `--disable-wallet`.
-* SQLite is not needed with `--disable-wallet`.
+* Berkeley DB is not needed with `--disable-wallet` or `--without-bdb`.
+* SQLite is not needed with `--disable-wallet` or `--without-sqlite`.
* Qt is not needed with `--without-gui`.
* If the qrencode dependency is absent, QR support won't be added. To force an error when that happens, pass `--with-qrencode`.
* ZeroMQ is needed only with the `--with-zmq` option.
diff --git a/doc/descriptors.md b/doc/descriptors.md
index 181ff77e50..63acb9167f 100644
--- a/doc/descriptors.md
+++ b/doc/descriptors.md
@@ -50,7 +50,7 @@ Output descriptors currently support:
- `wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))` describes a P2WSH *2-of-3* multisig output with keys in the specified order.
- `sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))` describes a P2SH-P2WSH *1-of-3* multisig output with keys in the specified order.
- `pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)` describes a P2PK output with the public key of the specified xpub.
-- `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2)` describes a P2PKH output with child key *1'/2* of the specified xpub.
+- `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1/2)` describes a P2PKH output with child key *1/2* of the specified xpub.
- `pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)` describes a set of P2PKH outputs, but additionally specifies that the specified xpub is a child of a master with fingerprint `d34db33f`, and derived using path `44'/0'/0'`.
- `wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where the first multisig key is the *1/0/`i`* child of the first specified xpub and the second multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default).
- `wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where one multisig key is the *1/0/`i`* child of the first specified xpub and the other multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). The order of public keys in the resulting witnessScripts is determined by the lexicographic order of the public keys at that index.
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index fa188dbcd6..9cb416bb30 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -276,6 +276,33 @@ configure option adds `-DDEBUG_LOCKORDER` to the compiler flags. This inserts
run-time checks to keep track of which locks are held and adds warnings to the
`debug.log` file if inconsistencies are detected.
+### Assertions and Checks
+
+The util file `src/util/check.h` offers helpers to protect against coding and
+internal logic bugs. They must never be used to validate user, network or any
+other input.
+
+* `assert` or `Assert` should be used to document assumptions when any
+ violation would mean that it is not safe to continue program execution. The
+ code is always compiled with assertions enabled.
+ - For example, a nullptr dereference or any other logic bug in validation
+ code means the program code is faulty and must terminate immediately.
+* `CHECK_NONFATAL` should be used for recoverable internal logic bugs. On
+ failure, it will throw an exception, which can be caught to recover from the
+ error.
+ - For example, a nullptr dereference or any other logic bug in RPC code
+ means that the RPC code is faulty and can not be executed. However, the
+ logic bug can be shown to the user and the program can continue to run.
+* `Assume` should be used to document assumptions when program execution can
+ safely continue even if the assumption is violated. In debug builds it
+ behaves like `Assert`/`assert` to notify developers and testers about
+ nonfatal errors. In production it doesn't warn or log anything, though the
+ expression is always evaluated.
+ - For example it can be assumed that a variable is only initialized once,
+ but a failed assumption does not result in a fatal bug. A failed
+ assumption may or may not result in a slightly degraded user experience,
+ but it is safe to continue program execution.
+
### Valgrind suppressions file
Valgrind is a programming tool for memory debugging, memory leak detection, and
diff --git a/doc/files.md b/doc/files.md
index e3f195de43..545e8fc92c 100644
--- a/doc/files.md
+++ b/doc/files.md
@@ -8,6 +8,10 @@
- [Multi-wallet environment](#multi-wallet-environment)
+ - [Berkeley DB database based wallets](#berkeley-db-database-based-wallets)
+
+ - [SQLite database based wallets](#sqlite-database-based-wallets)
+
- [GUI settings](#gui-settings)
- [Legacy subdirectories and files](#legacy-subdirectories-and-files)
@@ -50,6 +54,7 @@ Subdirectory | File(s) | Description
`indexes/blockfilter/basic/db/` | LevelDB database | Blockfilter index LevelDB database for the basic filtertype; *optional*, used if `-blockfilterindex=basic`
`indexes/blockfilter/basic/` | `fltrNNNNN.dat`<sup>[\[2\]](#note2)</sup> | Blockfilter index filters for the basic filtertype; *optional*, used if `-blockfilterindex=basic`
`wallets/` | | [Contains wallets](#multi-wallet-environment); can be specified by `-walletdir` option; if `wallets/` subdirectory does not exist, wallets reside in the [data directory](#data-directory-location)
+`./` | `anchors.dat` | Anchor IP address database, created on shutdown and deleted at startup. Anchors are last known outgoing block-relay-only peers that are tried to re-connect to on startup
`./` | `banlist.dat` | Stores the IPs/subnets of banned nodes
`./` | `bitcoin.conf` | User-defined [configuration settings](bitcoin-conf.md) for `bitcoind` or `bitcoin-qt`. File is not written to by the software and must be created manually. Path can be specified by `-conf` option
`./` | `bitcoind.pid` | Stores the process ID (PID) of `bitcoind` or `bitcoin-qt` while running; created at start and deleted on shutdown; can be specified by `-pid` option
@@ -66,26 +71,36 @@ Subdirectory | File(s) | Description
## Multi-wallet environment
-Wallets are Berkeley DB (BDB) databases:
+Wallets are Berkeley DB (BDB) or SQLite databases.
-Subdirectory | File(s) | Description
--------------|-------------------|------------
-`database/` | BDB logging files | Part of BDB environment; created at start and deleted on shutdown; a user *must keep it as safe* as personal wallet `wallet.dat`
-`./` | `db.log` | BDB error file
-`./` | `wallet.dat` | Personal wallet with keys and transactions. May be either a Berkeley DB or SQLite database file.
-`./` | `.walletlock` | Wallet lock file
-`./` | `wallet.dat-journal` | SQLite Rollback Journal file for `wallet.dat`. Usually created at start and deleted on shutdown. A user *must keep it as safe* as the `wallet.dat` file.
-
-1. Each user-defined wallet named "wallet_name" resides in `wallets/wallet_name/` subdirectory.
+1. Each user-defined wallet named "wallet_name" resides in the `wallets/wallet_name/` subdirectory.
2. The default (unnamed) wallet resides in `wallets/` subdirectory; if the latter does not exist, the wallet resides in the data directory.
-3. A wallet database path can be specified by `-wallet` option.
+3. A wallet database path can be specified with the `-wallet` option.
4. `wallet.dat` files must not be shared across different node instances, as that can result in key-reuse and double-spends due the lack of synchronization between instances.
5. Any copy or backup of the wallet should be done through a `backupwallet` call in order to update and lock the wallet, preventing any file corruption caused by updates during the copy.
+
+### Berkeley DB database based wallets
+
+Subdirectory | File(s) | Description
+-------------|-------------------|-------------
+`database/` | BDB logging files | Part of BDB environment; created at start and deleted on shutdown; a user *must keep it as safe* as personal wallet `wallet.dat`
+`./` | `db.log` | BDB error file
+`./` | `wallet.dat` | Personal wallet (a BDB database) with keys and transactions
+`./` | `.walletlock` | BDB wallet lock file
+
+### SQLite database based wallets
+
+Subdirectory | File | Description
+-------------|----------------------|-------------
+`./` | `wallet.dat` | Personal wallet (a SQLite database) with keys and transactions
+`./` | `wallet.dat-journal` | SQLite Rollback Journal file for `wallet.dat`. Usually created at start and deleted on shutdown. A user *must keep it as safe* as the `wallet.dat` file.
+
+
## GUI settings
`bitcoin-qt` uses [`QSettings`](https://doc.qt.io/qt-5/qsettings.html) class; this implies platform-specific [locations where application settings are stored](https://doc.qt.io/qt-5/qsettings.html#locations-where-application-settings-are-stored).
diff --git a/doc/fuzzing.md b/doc/fuzzing.md
index c97b8d4d50..80ce821091 100644
--- a/doc/fuzzing.md
+++ b/doc/fuzzing.md
@@ -12,7 +12,7 @@ $ CC=clang CXX=clang++ ./configure --enable-fuzz --with-sanitizers=address,fuzze
# macOS users: If you have problem with this step then make sure to read "macOS hints for
# libFuzzer" on https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md#macos-hints-for-libfuzzer
$ make
-$ src/test/fuzz/process_message
+$ FUZZ=process_message src/test/fuzz/fuzz
# abort fuzzing using ctrl-c
```
@@ -26,7 +26,7 @@ If you specify a corpus directory then any new coverage increasing inputs will b
```sh
$ mkdir -p process_message-seeded-from-thin-air/
-$ src/test/fuzz/process_message process_message-seeded-from-thin-air/
+$ FUZZ=process_message src/test/fuzz/fuzz process_message-seeded-from-thin-air/
INFO: Seed: 840522292
INFO: Loaded 1 modules (424174 inline 8-bit counters): 424174 [0x55e121ef9ab8, 0x55e121f613a6),
INFO: Loaded 1 PC tables (424174 PCs): 424174 [0x55e121f613a8,0x55e1225da288),
@@ -70,7 +70,7 @@ To fuzz `process_message` using the [`bitcoin-core/qa-assets`](https://github.co
```sh
$ git clone https://github.com/bitcoin-core/qa-assets
-$ src/test/fuzz/process_message qa-assets/fuzz_seed_corpus/process_message/
+$ FUZZ=process_message src/test/fuzz/fuzz qa-assets/fuzz_seed_corpus/process_message/
INFO: Seed: 1346407872
INFO: Loaded 1 modules (424174 inline 8-bit counters): 424174 [0x55d8a9004ab8, 0x55d8a906c3a6),
INFO: Loaded 1 PC tables (424174 PCs): 424174 [0x55d8a906c3a8,0x55d8a96e5288),
@@ -129,7 +129,7 @@ $ make
# try compiling using: AFL_NO_X86=1 make
$ mkdir -p inputs/ outputs/
$ echo A > inputs/thin-air-input
-$ afl/afl-fuzz -i inputs/ -o outputs/ -- src/test/fuzz/bech32
+$ FUZZ=bech32 afl/afl-fuzz -i inputs/ -o outputs/ -- src/test/fuzz/fuzz
# You may have to change a few kernel parameters to test optimally - afl-fuzz
# will print an error and suggestion if so.
```
@@ -153,7 +153,7 @@ $ cd ..
$ CC=$(pwd)/honggfuzz/hfuzz_cc/hfuzz-clang CXX=$(pwd)/honggfuzz/hfuzz_cc/hfuzz-clang++ ./configure --enable-fuzz --with-sanitizers=address,undefined
$ make
$ mkdir -p inputs/
-$ honggfuzz/honggfuzz -i inputs/ -- src/test/fuzz/process_message
+$ FUZZ=process_message honggfuzz/honggfuzz -i inputs/ -- src/test/fuzz/fuzz
```
Read the [Honggfuzz documentation](https://github.com/google/honggfuzz/blob/master/docs/USAGE.md) for more information.
diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1
index 129651d8e9..588ae81fce 100644
--- a/doc/man/bitcoin-cli.1
+++ b/doc/man/bitcoin-cli.1
@@ -1,115 +1,5 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
-.TH BITCOIN-CLI "1" "February 2019" "bitcoin-cli v0.17.99.0" "User Commands"
+.TH BITCOIN-CLI "1"
.SH NAME
-bitcoin-cli \- manual page for bitcoin-cli v0.17.99.0
-.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 v0.17.99.0
-.SH OPTIONS
-.HP
-\-?
-.IP
-Print this help message and exit
-.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\-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\-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, 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\-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.
-.HP
-\fB\-version\fR
-.IP
-Print version and exit
-.PP
-Chain selection options:
-.HP
-\fB\-testnet\fR
-.IP
-Use the test chain
-.SH COPYRIGHT
-Copyright (C) 2009-2019 The Bitcoin Core developers
+bitcoin-cli \- manual page for bitcoin-cli
-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>
+This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1
index f68be21e8d..9c75e9fe54 100644
--- a/doc/man/bitcoin-qt.1
+++ b/doc/man/bitcoin-qt.1
@@ -1,610 +1,5 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
-.TH BITCOIN-QT "1" "February 2019" "bitcoin-qt v0.17.99.0" "User Commands"
+.TH BITCOIN-QT "1"
.SH NAME
-bitcoin-qt \- manual page for bitcoin-qt v0.17.99.0
-.SH SYNOPSIS
-.B bitcoin-qt
-[\fI\,command-line options\/\fR]
-.SH DESCRIPTION
-Bitcoin Core version v0.17.99.0 (64\-bit)
-.SH OPTIONS
-.HP
-\-?
-.IP
-Print this help message and exit
-.HP
-\fB\-alertnotify=\fR<cmd>
-.IP
-Execute command when a relevant alert is received or we see a really
-long fork (%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:
-0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8,
-testnet:
-0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75)
-.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 blocks directory (default: <datadir>/blocks)
-.HP
-\fB\-conf=\fR<file>
-.IP
-Specify configuration file. Relative paths will be prefixed by datadir
-location. (default: bitcoin.conf)
-.HP
-\fB\-daemon\fR
-.IP
-Run in the background as a daemon and accept commands
-.HP
-\fB\-datadir=\fR<dir>
-.IP
-Specify data directory
-.HP
-\fB\-dbcache=\fR<n>
-.IP
-Set database cache size in MiB (4 to 16384, default: 450)
-.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 blk000??.dat 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\-8\fR to 16, 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 and \fB\-rescan\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
-.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.
-.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 command help for more info). This option can be
-specified multiple times to add multiple nodes.
-.HP
-\fB\-banscore=\fR<n>
-.IP
-Threshold for disconnecting misbehaving peers (default: 100)
-.HP
-\fB\-bantime=\fR<n>
-.IP
-Number of seconds to keep misbehaving peers from reconnecting (default:
-86400)
-.HP
-\fB\-bind=\fR<addr>
-.IP
-Bind to given address and always listen on it. Use [host]:port notation
-for IPv6
-.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\-forcednsseed\fR
-.IP
-Always query for peer addresses via DNS lookup (default: 0)
-.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 hidden service (default: 1)
-.HP
-\fB\-maxconnections=\fR<n>
-.IP
-Maintain at most <n> connections to peers (default: 125)
-.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 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 (in MiB per 24h),
-0 = no limit (default: 0)
-.HP
-\fB\-onion=\fR<ip:port>
-.IP
-Use separate SOCKS5 proxy to reach peers via Tor hidden services, set
-\fB\-noonion\fR to disable (default: \fB\-proxy\fR)
-.HP
-\fB\-onlynet=\fR<net>
-.IP
-Make outgoing connections only through network <net> (ipv4, ipv6 or
-onion). Incoming connections are not affected by this option.
-This option can be specified multiple times to allow multiple
-networks.
-.HP
-\fB\-peerbloomfilters\fR
-.IP
-Support filtering of blocks and transaction with bloom filters (default:
-1)
-.HP
-\fB\-permitbaremultisig\fR
-.IP
-Relay non\-P2SH multisig (default: 1)
-.HP
-\fB\-port=\fR<port>
-.IP
-Listen for connections on <port> (default: 8333, testnet: 18333,
-regtest: 18444)
-.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 connection timeout in milliseconds (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<addr>
-.IP
-Bind to given address and whitelist peers connecting to it. Use
-[host]:port notation for IPv6
-.HP
-\fB\-whitelist=\fR<IP address or network>
-.IP
-Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or
-CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple
-times. Whitelisted peers cannot be DoS banned and their
-transactions are always relayed, even if they are already in the
-mempool, useful e.g. for a gateway
-.PP
-Wallet options:
-.HP
-\fB\-addresstype\fR
-.IP
-What type of addresses to use ("legacy", "p2sh\-segwit", or "bech32",
-default: "p2sh\-segwit")
-.HP
-\fB\-avoidpartialspends\fR
-.IP
-Group outputs by address, selecting all or none, instead of selecting on
-a per\-output basis. Privacy is improved as an address is only
-used once (unless someone sends to it after spending from it),
-but may result in slightly higher fees as suboptimal coin
-selection may result due to the added limitation (default: 0)
-.HP
-\fB\-changetype\fR
-.IP
-What type of change to use ("legacy", "p2sh\-segwit", or "bech32").
-Default is same as \fB\-addresstype\fR, except when
-\fB\-addresstype\fR=\fI\,p2sh\-segwit\/\fR a native segwit output is used when
-sending to a native segwit address)
-.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/kB) 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/kB) that will be used when fee estimation has
-insufficient data (default: 0.0002)
-.HP
-\fB\-keypool=\fR<n>
-.IP
-Set key pool size to <n> (default: 1000)
-.HP
-\fB\-mintxfee=\fR<amt>
-.IP
-Fees (in BTC/kB) smaller than this are considered zero fee for
-transaction creation (default: 0.00001)
-.HP
-\fB\-paytxfee=\fR<amt>
-.IP
-Fee (in BTC/kB) to add to transactions you send (default: 0.00)
-.HP
-\fB\-rescan\fR
-.IP
-Rescan the block chain for missing wallet transactions on startup
-.HP
-\fB\-salvagewallet\fR
-.IP
-Attempt to recover private keys from a corrupt wallet on startup
-.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\-upgradewallet\fR
-.IP
-Upgrade wallet to latest format on startup
-.HP
-\fB\-wallet=\fR<path>
-.IP
-Specify wallet database path. Can be specified multiple times to load
-multiple wallets. Path is interpreted relative to <walletdir> if
-it is not absolute, and will be created if it does not exist (as
-a directory containing a wallet.dat file and log files). For
-backwards compatibility this will also accept names of existing
-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)
-.HP
-\fB\-walletrbf\fR
-.IP
-Send transactions with full\-RBF opt\-in enabled (RPC only, default: 0)
-.HP
-\fB\-zapwallettxes=\fR<mode>
-.IP
-Delete all wallet transactions and only recover those parts of the
-blockchain through \fB\-rescan\fR on startup (1 = keep tx meta data e.g.
-payment request information, 2 = drop tx meta data)
-.PP
-ZeroMQ notification options:
-.HP
-\fB\-zmqpubhashblock=\fR<address>
-.IP
-Enable publish hash block in <address>
-.HP
-\fB\-zmqpubhashtx=\fR<address>
-.IP
-Enable publish hash transaction in <address>
-.HP
-\fB\-zmqpubrawblock=\fR<address>
-.IP
-Enable publish raw block in <address>
-.HP
-\fB\-zmqpubrawtx=\fR<address>
-.IP
-Enable publish raw transaction in <address>
-.PP
-Debugging/Testing options:
-.HP
-\fB\-debug=\fR<category>
-.IP
-Output debugging information (default: \fB\-nodebug\fR, supplying <category> is
-optional). If <category> is not supplied or if <category> = 1,
-output all debugging information. <category> can be: net, tor,
-mempool, http, bench, zmq, db, rpc, estimatefee, addrman,
-selectcoins, reindex, cmpctblock, rand, prune, proxy, mempoolrej,
-libevent, coindb, qt, leveldb.
-.HP
-\fB\-debugexclude=\fR<category>
-.IP
-Exclude debugging information for a category. Can be used in conjunction
-with \fB\-debug\fR=\fI\,1\/\fR to output debug logs for all categories except one
-or more specified 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\-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 or raw
-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\-testnet\fR
-.IP
-Use the test chain
-.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
-.HP
-\fB\-minrelaytxfee=\fR<amt>
-.IP
-Fees (in BTC/kB) smaller than this are considered zero fee for relaying,
-mining and transaction creation (default: 0.00001)
-.HP
-\fB\-whitelistforcerelay\fR
-.IP
-Force relay of transactions from whitelisted peers even if they violate
-local relay policy (default: 0)
-.HP
-\fB\-whitelistrelay\fR
-.IP
-Accept relayed transactions received from whitelisted peers 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/kB) 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, 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\-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\-rootcertificates=\fR<file>
-.IP
-Set SSL root certificates for payment request (default: \fB\-system\-\fR)
-.HP
-\fB\-splash\fR
-.IP
-Show splash screen on startup (default: 1)
-.SH COPYRIGHT
-Copyright (C) 2009-2019 The Bitcoin Core developers
+bitcoin-qt \- manual page for bitcoin-qt
-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>
+This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1
index b4c7698896..148a5890b0 100644
--- a/doc/man/bitcoin-tx.1
+++ b/doc/man/bitcoin-tx.1
@@ -1,116 +1,5 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
-.TH BITCOIN-TX "1" "February 2019" "bitcoin-tx v0.17.99.0" "User Commands"
+.TH BITCOIN-TX "1"
.SH NAME
-bitcoin-tx \- manual page for bitcoin-tx v0.17.99.0
-.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 v0.17.99.0
-.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.
-.PP
-Chain selection options:
-.HP
-\fB\-testnet\fR
-.IP
-Use the test chain
-.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-2019 The Bitcoin Core developers
+bitcoin-tx \- manual page for bitcoin-tx
-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>
+This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
diff --git a/doc/man/bitcoin-wallet.1 b/doc/man/bitcoin-wallet.1
index aadea09a2b..69133b33f7 100644
--- a/doc/man/bitcoin-wallet.1
+++ b/doc/man/bitcoin-wallet.1
@@ -1,63 +1,5 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
-.TH BITCOIN-WALLET "1" "February 2019" "bitcoin-wallet v0.17.99.0" "User Commands"
+.TH BITCOIN-WALLET "1"
.SH NAME
-bitcoin-wallet \- manual page for bitcoin-wallet v0.17.99.0
-.SH DESCRIPTION
-Bitcoin Core bitcoin\-wallet version v0.17.99.0
-.PP
-wallet\-tool is an offline tool for creating and interacting with Bitcoin Core wallet files.
-By default wallet\-tool 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\-testnet\fR/\-regtest 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\-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\-testnet\fR
-.IP
-Use the test chain
-.PP
-Commands:
-.IP
-create
-.IP
-Create new wallet file
-.IP
-info
-.IP
-Get wallet info
-.SH COPYRIGHT
-Copyright (C) 2009-2019 The Bitcoin Core developers
+bitcoin-wallet \- manual page for bitcoin-wallet
-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>
+This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1
index 211ba10285..de338182ff 100644
--- a/doc/man/bitcoind.1
+++ b/doc/man/bitcoind.1
@@ -1,583 +1,5 @@
-.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
-.TH BITCOIND "1" "February 2019" "bitcoind v0.17.99.0" "User Commands"
+.TH BITCOIND "1"
.SH NAME
-bitcoind \- manual page for bitcoind v0.17.99.0
-.SH SYNOPSIS
-.B bitcoind
-[\fI\,options\/\fR] \fI\,Start Bitcoin Core Daemon\/\fR
-.SH DESCRIPTION
-Bitcoin Core Daemon version v0.17.99.0
-.SH OPTIONS
-.HP
-\-?
-.IP
-Print this help message and exit
-.HP
-\fB\-alertnotify=\fR<cmd>
-.IP
-Execute command when a relevant alert is received or we see a really
-long fork (%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:
-0000000000000000002e63058c023a9a1de233554f28c7b21380b6c9003f36a8,
-testnet:
-0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75)
-.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 blocks directory (default: <datadir>/blocks)
-.HP
-\fB\-conf=\fR<file>
-.IP
-Specify configuration file. Relative paths will be prefixed by datadir
-location. (default: bitcoin.conf)
-.HP
-\fB\-daemon\fR
-.IP
-Run in the background as a daemon and accept commands
-.HP
-\fB\-datadir=\fR<dir>
-.IP
-Specify data directory
-.HP
-\fB\-dbcache=\fR<n>
-.IP
-Set database cache size in MiB (4 to 16384, default: 450)
-.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 blk000??.dat 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\-8\fR to 16, 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 and \fB\-rescan\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
-.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.
-.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 command help for more info). This option can be
-specified multiple times to add multiple nodes.
-.HP
-\fB\-banscore=\fR<n>
-.IP
-Threshold for disconnecting misbehaving peers (default: 100)
-.HP
-\fB\-bantime=\fR<n>
-.IP
-Number of seconds to keep misbehaving peers from reconnecting (default:
-86400)
-.HP
-\fB\-bind=\fR<addr>
-.IP
-Bind to given address and always listen on it. Use [host]:port notation
-for IPv6
-.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\-forcednsseed\fR
-.IP
-Always query for peer addresses via DNS lookup (default: 0)
-.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 hidden service (default: 1)
-.HP
-\fB\-maxconnections=\fR<n>
-.IP
-Maintain at most <n> connections to peers (default: 125)
-.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 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 (in MiB per 24h),
-0 = no limit (default: 0)
-.HP
-\fB\-onion=\fR<ip:port>
-.IP
-Use separate SOCKS5 proxy to reach peers via Tor hidden services, set
-\fB\-noonion\fR to disable (default: \fB\-proxy\fR)
-.HP
-\fB\-onlynet=\fR<net>
-.IP
-Make outgoing connections only through network <net> (ipv4, ipv6 or
-onion). Incoming connections are not affected by this option.
-This option can be specified multiple times to allow multiple
-networks.
-.HP
-\fB\-peerbloomfilters\fR
-.IP
-Support filtering of blocks and transaction with bloom filters (default:
-1)
-.HP
-\fB\-permitbaremultisig\fR
-.IP
-Relay non\-P2SH multisig (default: 1)
-.HP
-\fB\-port=\fR<port>
-.IP
-Listen for connections on <port> (default: 8333, testnet: 18333,
-regtest: 18444)
-.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 connection timeout in milliseconds (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<addr>
-.IP
-Bind to given address and whitelist peers connecting to it. Use
-[host]:port notation for IPv6
-.HP
-\fB\-whitelist=\fR<IP address or network>
-.IP
-Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or
-CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple
-times. Whitelisted peers cannot be DoS banned and their
-transactions are always relayed, even if they are already in the
-mempool, useful e.g. for a gateway
-.PP
-Wallet options:
-.HP
-\fB\-addresstype\fR
-.IP
-What type of addresses to use ("legacy", "p2sh\-segwit", or "bech32",
-default: "p2sh\-segwit")
-.HP
-\fB\-avoidpartialspends\fR
-.IP
-Group outputs by address, selecting all or none, instead of selecting on
-a per\-output basis. Privacy is improved as an address is only
-used once (unless someone sends to it after spending from it),
-but may result in slightly higher fees as suboptimal coin
-selection may result due to the added limitation (default: 0)
-.HP
-\fB\-changetype\fR
-.IP
-What type of change to use ("legacy", "p2sh\-segwit", or "bech32").
-Default is same as \fB\-addresstype\fR, except when
-\fB\-addresstype\fR=\fI\,p2sh\-segwit\/\fR a native segwit output is used when
-sending to a native segwit address)
-.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/kB) 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/kB) that will be used when fee estimation has
-insufficient data (default: 0.0002)
-.HP
-\fB\-keypool=\fR<n>
-.IP
-Set key pool size to <n> (default: 1000)
-.HP
-\fB\-mintxfee=\fR<amt>
-.IP
-Fees (in BTC/kB) smaller than this are considered zero fee for
-transaction creation (default: 0.00001)
-.HP
-\fB\-paytxfee=\fR<amt>
-.IP
-Fee (in BTC/kB) to add to transactions you send (default: 0.00)
-.HP
-\fB\-rescan\fR
-.IP
-Rescan the block chain for missing wallet transactions on startup
-.HP
-\fB\-salvagewallet\fR
-.IP
-Attempt to recover private keys from a corrupt wallet on startup
-.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\-upgradewallet\fR
-.IP
-Upgrade wallet to latest format on startup
-.HP
-\fB\-wallet=\fR<path>
-.IP
-Specify wallet database path. Can be specified multiple times to load
-multiple wallets. Path is interpreted relative to <walletdir> if
-it is not absolute, and will be created if it does not exist (as
-a directory containing a wallet.dat file and log files). For
-backwards compatibility this will also accept names of existing
-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)
-.HP
-\fB\-walletrbf\fR
-.IP
-Send transactions with full\-RBF opt\-in enabled (RPC only, default: 0)
-.HP
-\fB\-zapwallettxes=\fR<mode>
-.IP
-Delete all wallet transactions and only recover those parts of the
-blockchain through \fB\-rescan\fR on startup (1 = keep tx meta data e.g.
-payment request information, 2 = drop tx meta data)
-.PP
-ZeroMQ notification options:
-.HP
-\fB\-zmqpubhashblock=\fR<address>
-.IP
-Enable publish hash block in <address>
-.HP
-\fB\-zmqpubhashtx=\fR<address>
-.IP
-Enable publish hash transaction in <address>
-.HP
-\fB\-zmqpubrawblock=\fR<address>
-.IP
-Enable publish raw block in <address>
-.HP
-\fB\-zmqpubrawtx=\fR<address>
-.IP
-Enable publish raw transaction in <address>
-.PP
-Debugging/Testing options:
-.HP
-\fB\-debug=\fR<category>
-.IP
-Output debugging information (default: \fB\-nodebug\fR, supplying <category> is
-optional). If <category> is not supplied or if <category> = 1,
-output all debugging information. <category> can be: net, tor,
-mempool, http, bench, zmq, db, rpc, estimatefee, addrman,
-selectcoins, reindex, cmpctblock, rand, prune, proxy, mempoolrej,
-libevent, coindb, qt, leveldb.
-.HP
-\fB\-debugexclude=\fR<category>
-.IP
-Exclude debugging information for a category. Can be used in conjunction
-with \fB\-debug\fR=\fI\,1\/\fR to output debug logs for all categories except one
-or more specified 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\-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 or raw
-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\-testnet\fR
-.IP
-Use the test chain
-.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\-minrelaytxfee=\fR<amt>
-.IP
-Fees (in BTC/kB) smaller than this are considered zero fee for relaying,
-mining and transaction creation (default: 0.00001)
-.HP
-\fB\-whitelistforcerelay\fR
-.IP
-Force relay of transactions from whitelisted peers even if they violate
-local relay policy (default: 0)
-.HP
-\fB\-whitelistrelay\fR
-.IP
-Accept relayed transactions received from whitelisted peers 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/kB) 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, 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\-server\fR
-.IP
-Accept command line and JSON\-RPC commands
-.SH COPYRIGHT
-Copyright (C) 2009-2019 The Bitcoin Core developers
+bitcoind \- manual page for bitcoind
-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>
+This is a placefolder file. Please follow the instructions in \fIcontrib/devtools/README.md\fR to generate the manual pages after a release.
diff --git a/doc/release-notes-19776.md b/doc/release-notes-19776.md
new file mode 100644
index 0000000000..5553c5a7bd
--- /dev/null
+++ b/doc/release-notes-19776.md
@@ -0,0 +1,9 @@
+Updated RPCs
+------------
+
+- The `getpeerinfo` RPC returns two new boolean fields, `bip152_hb_to` and
+ `bip152_hb_from`, that respectively indicate whether we selected a peer to be
+ in compact blocks high-bandwidth mode or whether a peer selected us as a
+ compact blocks high-bandwidth peer. High-bandwidth peers send new block
+ announcements via a `cmpctblock` message rather than the usual inv/headers
+ announcements. See BIP 152 for more details. (#19776)
diff --git a/doc/release-notes-19988.md b/doc/release-notes-19988.md
deleted file mode 100644
index ef26eb3032..0000000000
--- a/doc/release-notes-19988.md
+++ /dev/null
@@ -1,9 +0,0 @@
-P2P changes
------------
-
-The size of the set of transactions that peers have announced and we consider
-for requests has been reduced from 100000 to 5000 (per peer), and further
-announcements will be ignored when that limit is reached. If you need to
-dump (very) large batches of transactions, exceptions can be made for trusted
-peers using the "relay" network permission. For localhost for example it can
-be enabled using the command line option `-whitelist=relay@127.0.0.1`.
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 65726f3d5d..f286a4493b 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -45,426 +45,61 @@ wallet versions of Bitcoin Core are generally supported.
Compatibility
==============
-During this release cycle, work has been done to ensure that the codebase is fully
-compatible with C++17. The intention is to begin using C++17 features starting
-with the 0.22.0 release. This means that a compiler that supports C++17 will be
-required to compile 0.22.0.
-
Bitcoin Core is supported and extensively tested on operating systems
-using the Linux kernel, macOS 10.12+, and Windows 7 and newer. Bitcoin
+using the Linux kernel, macOS 10.14+, 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.
-From Bitcoin Core 0.20.0 onwards, macOS versions earlier than 10.12 are no
+From Bitcoin Core 0.22.0 onwards, macOS versions earlier than 10.14 are no
longer supported. Additionally, Bitcoin Core does not yet change appearance
when macOS "dark mode" is activated.
-The node's known peers are persisted to disk in a file called `peers.dat`. The
-format of this file has been changed in a backwards-incompatible way in order to
-accommodate the storage of Tor v3 and other BIP155 addresses. This means that if
-the file is modified by 0.21.0 or newer then older versions will not be able to
-read it. Those old versions, in the event of a downgrade, will log an error
-message that deserialization has failed and will continue normal operation
-as if the file was missing, creating a new empty one. (#19954)
-
Notable changes
===============
P2P and network changes
-----------------------
-- The mempool now tracks whether transactions submitted via the wallet or RPCs
- have been successfully broadcast. Every 10-15 minutes, the node will try to
- announce unbroadcast transactions until a peer requests it via a `getdata`
- message or the transaction is removed from the mempool for other reasons.
- The node will not track the broadcast status of transactions submitted to the
- node using P2P relay. This version reduces the initial broadcast guarantees
- for wallet transactions submitted via P2P to a node running the wallet. (#18038)
-
-- The Tor onion service that is automatically created by setting the
- `-listenonion` configuration parameter will now be created as a Tor v3 service
- instead of Tor v2. The private key that was used for Tor v2 (if any) will be
- left untouched in the `onion_private_key` file in the data directory (see
- `-datadir`) and can be removed if not needed. Bitcoin Core will no longer
- attempt to read it. The private key for the Tor v3 service will be saved in a
- file named `onion_v3_private_key`. To use the deprecated Tor v2 service (not
- recommended), then `onion_private_key` can be copied over
- `onion_v3_private_key`, e.g.
- `cp -f onion_private_key onion_v3_private_key`. (#19954)
-
Updated RPCs
------------
-- The `getpeerinfo` RPC now has additional `last_block` and `last_transaction`
- fields that return the UNIX epoch time of the last block and the last valid
- transaction received from each peer. (#19731)
-
-- `getnetworkinfo` now returns two new fields, `connections_in` and
- `connections_out`, that provide the number of inbound and outbound peer
- connections. These new fields are in addition to the existing `connections`
- field, which returns the total number of peer connections. (#19405)
-
-- Exposed transaction version numbers are now treated as unsigned 32-bit
- integers instead of signed 32-bit integers. This matches their treatment in
- consensus logic. Versions greater than 2 continue to be non-standard
- (matching previous behavior of smaller than 1 or greater than 2 being
- non-standard). Note that this includes the joinpsbt command, which combines
- partially-signed transactions by selecting the highest version number.
- (#16525)
-
-- `getmempoolinfo` now returns an additional `unbroadcastcount` field. The
- mempool tracks locally submitted transactions until their initial broadcast
- is acknowledged by a peer. This field returns the count of transactions
- waiting for acknowledgement.
-
-- Mempool RPCs such as `getmempoolentry` and `getrawmempool` with
- `verbose=true` now return an additional `unbroadcast` field. This indicates
- whether initial broadcast of the transaction has been acknowledged by a
- peer. `getmempoolancestors` and `getmempooldescendants` are also updated.
-
-- The `bumpfee`, `fundrawtransaction`, `sendmany`, `sendtoaddress`, and `walletcreatefundedpsbt`
-RPC commands have been updated to include two new fee estimation methods "BTC/kB" and "sat/B".
-The target is the fee expressed explicitly in the given form. Note that use of this feature
-will trigger BIP 125 (replace-by-fee) opt-in. (#11413)
-
-- In addition, the `estimate_mode` parameter is now case insensitive for all of
- the above RPC commands. (#11413)
-
-- The `bumpfee` command now uses `conf_target` rather than `confTarget` in the
- options. (#11413)
-
-- The `getpeerinfo` RPC no longer returns the `banscore` field unless the configuration
- option `-deprecatedrpc=banscore` is used. The `banscore` field will be fully
- removed in the next major release. (#19469)
-
-- The `testmempoolaccept` RPC returns `vsize` and a `fees` object with the `base` fee
- if the transaction would pass validation. (#19940)
-
-- The `getpeerinfo` RPC now returns a `connection_type` field. This indicates
- the type of connection established with the peer. It will return one of six
- options. For more information, see the `getpeerinfo` help documentation.
- (#19725)
-
-- The `getpeerinfo` RPC no longer returns the `addnode` field by default. This
- field will be fully removed in the next major release. It can be accessed
- with the configuration option `-deprecatedrpc=getpeerinfo_addnode`. However,
- it is recommended to instead use the `connection_type` field (it will return
- `manual` when addnode is true). (#19725)
-
-- The `walletcreatefundedpsbt` RPC call will now fail with
- `Insufficient funds` when inputs are manually selected but are not enough to cover
- the outputs and fee. Additional inputs can automatically be added through the
- new `add_inputs` option. (#16377)
-
-- The `fundrawtransaction` RPC now supports `add_inputs` option that when `false`
- prevents adding more inputs if necessary and consequently the RPC fails.
-
Changes to Wallet or GUI related RPCs can be found in the GUI or Wallet section below.
New RPCs
--------
-- The `getindexinfo` RPC returns the actively running indices of the node,
- including their current sync status and height. It also accepts an `index_name`
- to specify returning only the status of that index. (#19550)
-
Build System
------------
+New settings
+------------
+
Updated settings
----------------
-- The same ZeroMQ notification (e.g. `-zmqpubhashtx=address`) can now be
- specified multiple times to publish the same notification to different ZeroMQ
- sockets. (#18309)
-
-- The `-banscore` configuration option, which modified the default threshold for
- disconnecting and discouraging misbehaving peers, has been removed as part of
- changes in 0.20.1 and in this release to the handling of misbehaving peers.
- Refer to "Changes regarding misbehaving peers" in the 0.20.1 release notes for
- details. (#19464)
-
-- The `-debug=db` logging category, which was deprecated in 0.20 and replaced by
- `-debug=walletdb` to distinguish it from `coindb`, has been removed. (#19202)
+Changes to Wallet or GUI related settings can be found in the GUI or Wallet section below.
-- A `download` permission has been extracted from the `noban` permission. For
- compatibility, `noban` implies the `download` permission, but this may change
- in future releases. Refer to the help of the affected settings `-whitebind`
- and `-whitelist` for more details. (#19191)
-
-- Netmasks that contain 1-bits after 0-bits (the 1-bits are not contiguous on
- the left side, e.g. 255.0.255.255) are no longer accepted. They are invalid
- according to RFC 4632. Netmasks are used in the `-rpcallowip` and `-whitelist`
- configuration options and in the `setban` RPC. (#19628)
-
-Changes to Wallet or GUI related settings can be found in the GUI or Wallet section below.
+- Passing an invalid `-rpcauth` argument now cause bitcoind to fail to start. (#20461)
Tools and Utilities
-------------------
-- The `connections` field of `bitcoin-cli -getinfo` is expanded to return a JSON
- object with `in`, `out` and `total` numbers of peer connections. It previously
- returned a single integer value for the total number of peer connections. (#19405)
-
-- A new `bitcoin-cli -generate` command, equivalent to RPC `generatenewaddress`
- followed by `generatetoaddress`, can generate blocks for command line testing
- purposes. This is a client-side version of the
- former `generate` RPC. See the help for details. (#19133)
-
-- The `bitcoin-cli -getinfo` command now displays the wallet name and balance for
- each of the loaded wallets when more than one is loaded (e.g. in multiwallet
- mode) and a wallet is not specified with `-rpcwallet`. (#18594)
-
-New settings
-------------
-
-- The `startupnotify` option is used to specify a command to
- execute when Bitcoin Core has finished with its startup
- sequence. (#15367)
-
Wallet
------
-- Backwards compatibility has been dropped for two `getaddressinfo` RPC
- deprecations, as notified in the 0.20 release notes. The deprecated `label`
- field has been removed as well as the deprecated `labels` behavior of
- returning a JSON object containing `name` and `purpose` key-value pairs. Since
- 0.20, the `labels` field returns a JSON array of label names. (#19200)
-
-- To improve wallet privacy, the frequency of wallet rebroadcast attempts is
- reduced from approximately once every 15 minutes to once every 12-36 hours.
- To maintain a similar level of guarantee for initial broadcast of wallet
- transactions, the mempool tracks these transactions as a part of the newly
- introduced unbroadcast set. See the "P2P and network changes" section for
- more information on the unbroadcast set. (#18038)
-
-- The `sendtoaddress` and `sendmany` RPCs accept an optional `verbose=True`
- argument to also return the fee reason about the sent tx. (#19501)
-
-- The wallet can create a transaction without change even when the keypool is
- empty. Previously it failed. (#17219)
-
-- The `-salvagewallet` startup option has been removed. A new `salvage` command
- has been added to the `bitcoin-wallet` tool which performs the salvage
- operations that `-salvagewallet` did. (#18918)
-
-- A new configuration flag `-maxapsfee` has been added, which sets the max
- allowed avoid partial spends (APS) fee. It defaults to 0 (i.e. fee is the
- same with and without APS). Setting it to -1 will disable APS, unless
- `-avoidpartialspends` is set. (#14582)
-
-- The wallet will now avoid partial spends (APS) by default, if this does not
- result in a difference in fees compared to the non-APS variant. The allowed
- fee threshold can be adjusted using the new `-maxapsfee` configuration
- option. (#14582)
-
-- The `createwallet`, `loadwallet`, and `unloadwallet` RPCs now accept
- `load_on_startup` options to modify the settings list. Unless these options
- are explicitly set to true or false, the list is not modified, so the RPC
- methods remain backwards compatible. (#15937)
-
-- A new `send` RPC with similar syntax to `walletcreatefundedpsbt`, including
- support for coin selection and a custom fee rate. The `send` RPC is
- experimental and may change in subsequent releases. Using it is encouraged
- once it's no longer experimental: `sendmany` and `sendtoaddress` may be
- deprecated in a future release. (#16378)
-
-- `fundrawtransaction` and `walletcreatefundedpsbt` when used with the
- `lockUnspents` argument now lock manually selected coins, in addition to
- automatically selected coins. Note that locked coins are never used in
- automatic coin selection, but can still be manually selected. (#18244)
-
-- The `-zapwallettxes` startup option has been removed and its functionality
- removed from the wallet. This option was originally intended to allow for
- the fee bumping of transactions that did not signal RBF. This functionality
- has been superseded with the abandon transaction feature. (#19671)
-
-- The error code when no wallet is loaded, but a wallet RPC is called, has been
- changed from `-32601` (method not found) to `-18` (wallet not found).
- (#20101)
-
-### Default Wallet
-
-Bitcoin Core will no longer create an unnamed `""` wallet by default when no
-wallet is specified on the command line or in the configuration files. For
-backwards compatibility, if an unnamed `""` wallet already exists and would
-have been loaded previously, then it will still be loaded. Users without an
-unnamed `""` wallet and without any other wallets to be loaded on startup will
-be prompted to either choose a wallet to load, or to create a new wallet.
-(#15454)
-
-### Experimental Descriptor Wallets
-
-Please note that Descriptor Wallets are still experimental and not all expected functionality
-is available. Additionally there may be some bugs and current functions may change in the future.
-Bugs and missing functionality can be reported to the [issue tracker](https://github.com/bitcoin/bitcoin/issues).
-
-0.21 introduces a new type of wallet - Descriptor Wallets. Descriptor Wallets store
-scriptPubKey information using descriptors. This is in contrast to the Legacy Wallet
-structure where keys are used to generate scriptPubKeys and addresses. Because of this
-shift to being script based instead of key based, many of the confusing things that Legacy
-Wallets do are not possible with Descriptor Wallets. Descriptor Wallets use a definition
-of "mine" for scripts which is simpler and more intuitive than that used by Legacy Wallets.
-Descriptor Wallets also uses different semantics for watch-only things and imports.
-
-As Descriptor Wallets are a new type of wallet, their introduction does not affect existing wallets.
-Users who already have a Bitcoin Core wallet can continue to use it as they did before without
-any change in behavior. Newly created Legacy Wallets (which is the default type of wallet) will
-behave as they did in previous versions of Bitcoin Core.
-
-The differences between Descriptor Wallets and Legacy Wallets are largely limited to non user facing
-things. They are intended to behave similarly except for the import/export and watchonly functionality
-as described below.
-
-#### Creating Descriptor Wallets
-
-Descriptor Wallets are not created by default. They must be explicitly created using the
-`createwallet` RPC or via the GUI. A `descriptors` option has been added to `createwallet`.
-Setting `descriptors` to `true` will create a Descriptor Wallet instead of a Legacy Wallet.
-
-In the GUI, a checkbox has been added to the Create Wallet Dialog to indicate that a
-Descriptor Wallet should be created.
-
-Without those options being set, a Legacy Wallet will be created instead. Additionally the
-Default Wallet created upon first startup of Bitcoin Core will be a Legacy Wallet.
-
-#### `IsMine` Semantics
-
-`IsMine` refers to the function used to determine whether a script belongs to the wallet.
-This is used to determine whether an output belongs to the wallet. `IsMine` in Legacy Wallets
-returns true if the wallet would be able to sign an input that spends an output with that script.
-Since keys can be involved in a variety of different scripts, this definition for `IsMine` can
-lead to many unexpected scripts being considered part of the wallet.
-
-With Descriptor Wallets, descriptors explicitly specify the set of scripts that are owned by
-the wallet. Since descriptors are deterministic and easily enumerable, users will know exactly
-what scripts the wallet will consider to belong to it. Additionally the implementation of `IsMine`
-in Descriptor Wallets is far simpler than for Legacy Wallets. Notably, in Legacy Wallets, `IsMine`
-allowed for users to take one type of address (e.g. P2PKH), mutate it into another address type
-(e.g. P2WPKH), and the wallet would still detect outputs sending to the new address type
-even without that address being requested from the wallet. Descriptor Wallets does not
-allow for this and will only watch for the addresses that were explicitly requested from the wallet.
-
-These changes to `IsMine` will make it easier to reason about what scripts the wallet will
-actually be watching for in outputs. However for the vast majority of users, this change is
-largely transparent and will not have noticeable effect.
-
-#### Imports and Exports
-
-In Legacy Wallets, raw scripts and keys could be imported to the wallet. Those imported scripts
-and keys are treated separately from the keys generated by the wallet. This complicates the `IsMine`
-logic as it has to distinguish between spendable and watchonly.
-
-Descriptor Wallets handle importing scripts and keys differently. Only complete descriptors can be
-imported. These descriptors are then added to the wallet as if it were a descriptor generated by
-the wallet itself. This simplifies the `IsMine` logic so that it no longer has to distinguish
-between spendable and watchonly. As such, the watchonly model for Descriptor Wallets is also
-different and described in more detail in the next section.
-
-To import into a Descriptor Wallet, a new `importdescriptors` RPC has been added that uses a syntax
-similar to that of `importmulti`.
-
-As Legacy Wallets and Descriptor Wallets use different mechanisms for storing and importing scripts and keys
-the existing import RPCs have been disabled for descriptor wallets.
-New export RPCs for Descriptor Wallets have not yet been added.
-
-The following RPCs are disabled for Descriptor Wallets:
-
-* importprivkey
-* importpubkey
-* importaddress
-* importwallet
-* dumpprivkey
-* dumpwallet
-* importmulti
-* addmultisigaddress
-* sethdseed
-
-#### Watchonly Wallets
-
-A Legacy Wallet contains both private keys and scripts that were being watched.
-Those watched scripts would not contribute to your normal balance. In order to see the watchonly
-balance and to use watchonly things in transactions, an `include_watchonly` option was added
-to many RPCs that would allow users to do that. However it is easy to forget to include this option.
-
-Descriptor Wallets move to a per-wallet watchonly model. Instead an entire wallet is considered to be
-watchonly depending on whether it was created with private keys disabled. This eliminates the need
-to distinguish between things that are watchonly and things that are not within a wallet itself.
-
-This change does have a caveat. If a Descriptor Wallet with private keys *enabled* has
-a multiple key descriptor without all of the private keys (e.g. `multi(...)` with only one private key),
-then the wallet will fail to sign and broadcast transactions. Such wallets would need to use the PSBT
-workflow but the typical GUI Send, `sendtoaddress`, etc. workflows would still be available, just
-non-functional.
-
-This issue is worsened if the wallet contains both single key (e.g. `wpkh(...)`) descriptors and such
-multiple key descriptors as some transactions could be signed and broadast and others not. This is
-due to some transactions containing only single key inputs, while others would contain both single
-key and multiple key inputs, depending on which are available and how the coin selection algorithm
-selects inputs. However this is not considered to be a supported use case; multisigs
-should be in their own wallets which do not already have descriptors. Although users cannot export
-descriptors with private keys for now as explained earlier.
-
-#### BIP 44/49/84 Support
-
-The change to using descriptors changes the default derivation paths used by Bitcoin Core
-to adhere to BIP 44/49/84. Descriptors with different derivation paths can be imported without
-issue.
-
-### Wallet RPC changes
-
-- The `upgradewallet` RPC replaces the `-upgradewallet` command line option.
- (#15761)
-- The `settxfee` RPC will fail if the fee was set higher than the `-maxtxfee`
- command line setting. The wallet will already fail to create transactions
- with fees higher than `-maxtxfee`. (#18467)
-
GUI changes
-----------
-- Wallets created or loaded in the GUI will now be automatically loaded on
- startup, so they don't need to be manually reloaded next time Bitcoin Core is
- started. The list of wallets to load on startup is stored in
- `\<datadir\>/settings.json` and augments any command line or `bitcoin.conf`
- `-wallet=` settings that specify more wallets to load. Wallets that are
- unloaded in the GUI get removed from the settings list so they won't load
- again automatically next startup. (#19754)
-
-- The GUI Peers window no longer displays a "Ban Score" field. This is part of
- changes in 0.20.1 and in this release to the handling of misbehaving
- peers. Refer to "Changes regarding misbehaving peers" in the 0.20.1 release
- notes for details. (#19512)
-
Low-level changes
=================
RPC
---
-- To make RPC `sendtoaddress` more consistent with `sendmany` the following error
- `sendtoaddress` codes were changed from `-4` to `-6`:
- - Insufficient funds
- - Fee estimation failed
- - Transaction has too long of a mempool chain
-
-- The `sendrawtransaction` error code for exceeding `maxfeerate` has been changed from
- `-26` to `-25`. The error string has been changed from "absurdly-high-fee" to
- "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)." The
- `testmempoolaccept` RPC returns `max-fee-exceeded` rather than `absurdly-high-fee`
- as the `reject-reason`. (#19339)
-
-- To make wallet and rawtransaction RPCs more consistent, the error message for
- exceeding maximum feerate has been changed to "Fee exceeds maximum configured by user
- (e.g. -maxtxfee, maxfeerate)." (#19339)
-
Tests
-----
-- The BIP 325 default signet can be enabled by the `-chain=signet` or `-signet`
- setting. The settings `-signetchallenge` and `-signetseednode` allow
- enabling a custom signet.
-
Credits
=======
diff --git a/doc/release-process.md b/doc/release-process.md
index a61b67c35f..cedb36d51d 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -18,20 +18,20 @@ Release Process
### Before every major release
* On both the master branch and the new release branch:
- - update `CLIENT_VERSION_MINOR` in [`configure.ac`](../configure.ac)
- - update `CLIENT_VERSION_MINOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h)
+ - update `CLIENT_VERSION_MAJOR` in [`configure.ac`](../configure.ac)
+ - update `CLIENT_VERSION_MAJOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h)
* On the new release branch in [`configure.ac`](../configure.ac) and [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) (see [this commit](https://github.com/bitcoin/bitcoin/commit/742f7dd)):
- - set `CLIENT_VERSION_REVISION` to `0`
+ - set `CLIENT_VERSION_MINOR` to `0`
+ - set `CLIENT_VERSION_BUILD` to `0`
- set `CLIENT_VERSION_IS_RELEASE` to `true`
#### Before branch-off
* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example.
-* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-m_assumed_blockchain_size-and-m_assumed_chain_state_size) for information on how to calculate them).
-* Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. Use the output of the RPC `getchaintxstats`, see
- [this pull request](https://github.com/bitcoin/bitcoin/pull/17002) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_last_block_hash>` with the `window_block_count` and `window_last_block_hash` from your output.
-* Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc.
-* Update `src/chainparams.cpp` defaultAssumeValid with information from the getblockhash rpc.
+* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-assumed-blockchain-and-chain-state-size) for information on how to calculate them).
+* Update [`src/chainparams.cpp`](/src/chainparams.cpp) chainTxData with statistics about the transaction count and rate. Use the output of the `getchaintxstats` RPC, see
+ [this pull request](https://github.com/bitcoin/bitcoin/pull/20263) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_final_block_hash>` with the `window_block_count` and `window_final_block_hash` from your output.
+* Update `src/chainparams.cpp` nMinimumChainWork and defaultAssumeValid (and the block height comment) with information from the `getblockheader` (and `getblockhash`) RPCs.
- The selected value must not be orphaned so it may be useful to set the value two blocks back from the tip.
- Testnet should be set some tens of thousands back from the tip due to reorgs there.
- This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect
@@ -371,7 +371,7 @@ bitcoin.org (see below for bitcoin.org update instructions).
### Additional information
-#### How to calculate `m_assumed_blockchain_size` and `m_assumed_chain_state_size`
+#### <a name="how-to-calculate-assumed-blockchain-and-chain-state-size"></a>How to calculate `m_assumed_blockchain_size` and `m_assumed_chain_state_size`
Both variables are used as a guideline for how much space the user needs on their drive in total, not just strictly for the blockchain.
Note that all values should be taken from a **fully synced** node and have an overhead of 5-10% added on top of its base value.
diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md
index e960863a80..147e223711 100644
--- a/doc/shared-libraries.md
+++ b/doc/shared-libraries.md
@@ -41,9 +41,10 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/sc
- `bitcoinconsensus_ERR_TX_SIZE_MISMATCH` - `txToLen` did not match with the size of `txTo`
- `bitcoinconsensus_ERR_DESERIALIZE` - An error deserializing `txTo`
- `bitcoinconsensus_ERR_AMOUNT_REQUIRED` - Input amount is required if WITNESS is used
+- `bitcoinconsensus_ERR_INVALID_FLAGS` - Script verification `flags` are invalid (i.e. not part of the libconsensus interface)
### Example Implementations
-- [NBitcoin](https://github.com/NicolasDorier/NBitcoin/blob/master/NBitcoin/Script.cs#L814) (.NET Bindings)
+- [NBitcoin](https://github.com/MetacoSA/NBitcoin/blob/5e1055cd7c4186dee4227c344af8892aea54faec/NBitcoin/Script.cs#L979-#L1031) (.NET Bindings)
- [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus) (Node.js Bindings)
- [java-libbitcoinconsensus](https://github.com/dexX7/java-libbitcoinconsensus) (Java Bindings)
- [bitcoinconsensus-php](https://github.com/Bit-Wasp/bitcoinconsensus-php) (PHP Bindings)
diff --git a/doc/tor.md b/doc/tor.md
index 34c5f1b5e7..86e5d9ddf3 100644
--- a/doc/tor.md
+++ b/doc/tor.md
@@ -47,7 +47,7 @@ In a typical situation, this suffices to run behind a Tor proxy:
./bitcoind -proxy=127.0.0.1:9050
-## 2. Run a Bitcoin Core hidden server
+## 2. Manually create a Bitcoin Core onion service
If you configure your Tor system accordingly, it is possible to make your node also
reachable from the Tor network. Add these lines to your /etc/tor/torrc (or equivalent
@@ -56,7 +56,6 @@ versions of Tor see [Section 3](#3-automatically-listen-on-tor).*
HiddenServiceDir /var/lib/tor/bitcoin-service/
HiddenServicePort 8333 127.0.0.1:8334
- HiddenServicePort 18333 127.0.0.1:18334
The directory can be different of course, but virtual port numbers should be equal to
your bitcoind's P2P listen port (8333 by default), and target addresses and ports
@@ -107,7 +106,7 @@ for normal IPv4/IPv6 communication, use:
./bitcoind -onion=127.0.0.1:9050 -externalip=7zvj7a2imdgkdbg4f2dryd5rgtrn7upivr5eeij4cicjh65pooxeshid.onion -discover
-## 3. Automatically listen on Tor
+## 3. Automatically create a Bitcoin Core onion service
Starting with Tor version 0.2.7.1 it is possible, through Tor's control socket
API, to create and destroy 'ephemeral' onion services programmatically.
@@ -145,6 +144,6 @@ in the tor configuration file. The hashed password can be obtained with the comm
- Do not add anything but Bitcoin Core ports to the onion service created in section 2.
If you run a web service too, create a new onion service for that.
- Otherwise it is trivial to link them, which may reduce privacy. Hidden
+ Otherwise it is trivial to link them, which may reduce privacy. Onion
services created automatically (as in section 3) always have only one port
open.
diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in
index 3befba3425..207d60aca3 100644
--- a/share/qt/Info.plist.in
+++ b/share/qt/Info.plist.in
@@ -3,7 +3,7 @@
<plist version="0.9">
<dict>
<key>LSMinimumSystemVersion</key>
- <string>10.12.0</string>
+ <string>10.14.0</string>
<key>LSArchitecturePriority</key>
<array>
@@ -17,13 +17,13 @@
<string>APPL</string>
<key>NSHumanReadableCopyright</key>
- <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string>
+ <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@, Copyright © 2009-@COPYRIGHT_YEAR@ @COPYRIGHT_HOLDERS_FINAL@</string>
<key>CFBundleShortVersionString</key>
- <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@</string>
+ <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@</string>
<key>CFBundleVersion</key>
- <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@</string>
+ <string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@</string>
<key>CFBundleSignature</key>
<string>????</string>
diff --git a/share/setup.nsi.in b/share/setup.nsi.in
index 5431909bb2..681f243d04 100644
--- a/share/setup.nsi.in
+++ b/share/setup.nsi.in
@@ -56,7 +56,7 @@ CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
-VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@.@CLIENT_VERSION_BUILD@
+VIProductVersion @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_BUILD@.0
VIAddVersionKey ProductName "@PACKAGE_NAME@"
VIAddVersionKey ProductVersion "@PACKAGE_VERSION@"
VIAddVersionKey CompanyName "${COMPANY}"
diff --git a/src/Makefile.am b/src/Makefile.am
index b0d36717ce..4a080ef1fb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,9 +20,8 @@ else
LIBUNIVALUE = $(UNIVALUE_LIBS)
endif
-BITCOIN_INCLUDES=-I$(builddir) $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS)
+BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/secp256k1/include $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS)
-BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS)
LIBBITCOIN_SERVER=libbitcoin_server.a
@@ -299,14 +298,13 @@ libbitcoin_server_a_SOURCES = \
index/blockfilterindex.cpp \
index/txindex.cpp \
init.cpp \
- interfaces/chain.cpp \
- interfaces/node.cpp \
miner.cpp \
net.cpp \
net_processing.cpp \
node/coin.cpp \
node/coinstats.cpp \
node/context.cpp \
+ node/interfaces.cpp \
node/psbt.cpp \
node/transaction.cpp \
node/ui_interface.cpp \
@@ -356,29 +354,33 @@ endif
# wallet: shared between bitcoind and bitcoin-qt, but only linked
# when wallet enabled
-libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(SQLITE_CFLAGS)
libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_wallet_a_SOURCES = \
- interfaces/wallet.cpp \
- wallet/bdb.cpp \
wallet/coincontrol.cpp \
wallet/context.cpp \
wallet/crypter.cpp \
wallet/db.cpp \
wallet/feebumper.cpp \
wallet/fees.cpp \
+ wallet/interfaces.cpp \
wallet/load.cpp \
wallet/rpcdump.cpp \
wallet/rpcwallet.cpp \
- wallet/salvage.cpp \
wallet/scriptpubkeyman.cpp \
- wallet/sqlite.cpp \
wallet/wallet.cpp \
wallet/walletdb.cpp \
wallet/walletutil.cpp \
wallet/coinselection.cpp \
$(BITCOIN_CORE_H)
+if USE_SQLITE
+libbitcoin_wallet_a_SOURCES += wallet/sqlite.cpp
+endif
+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_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_wallet_tool_a_SOURCES = \
diff --git a/src/Makefile.crc32c.include b/src/Makefile.crc32c.include
index 802b3a2e4b..113272e65e 100644
--- a/src/Makefile.crc32c.include
+++ b/src/Makefile.crc32c.include
@@ -41,7 +41,7 @@ crc32c_libcrc32c_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
crc32c_libcrc32c_a_SOURCES =
crc32c_libcrc32c_a_SOURCES += crc32c/include/crc32c/crc32c.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64.h
-crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64_linux_check.h
+crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_arm64_check.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_internal.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_prefetch.h
crc32c_libcrc32c_a_SOURCES += crc32c/src/crc32c_read_le.h
diff --git a/src/Makefile.qt_locale.include b/src/Makefile.qt_locale.include
index 17ba0780e6..aea42fd902 100644
--- a/src/Makefile.qt_locale.include
+++ b/src/Makefile.qt_locale.include
@@ -72,6 +72,7 @@ QT_TS = \
qt/locale/bitcoin_ta.ts \
qt/locale/bitcoin_te.ts \
qt/locale/bitcoin_th.ts \
+ qt/locale/bitcoin_tr.ts \
qt/locale/bitcoin_uk.ts \
qt/locale/bitcoin_ur.ts \
qt/locale/bitcoin_uz@Cyrl.ts \
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 7fac78f973..cbfe93df0a 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -2,169 +2,15 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-FUZZ_TARGETS = \
- test/fuzz/addition_overflow \
- test/fuzz/addr_info_deserialize \
- test/fuzz/addrdb \
- test/fuzz/address_deserialize \
- test/fuzz/addrman_deserialize \
- test/fuzz/asmap \
- test/fuzz/asmap_direct \
- test/fuzz/autofile \
- test/fuzz/banentry_deserialize \
- test/fuzz/banman \
- test/fuzz/base_encode_decode \
- test/fuzz/bech32 \
- test/fuzz/block \
- test/fuzz/block_deserialize \
- test/fuzz/block_file_info_deserialize \
- test/fuzz/block_filter_deserialize \
- test/fuzz/block_header \
- test/fuzz/block_header_and_short_txids_deserialize \
- test/fuzz/blockfilter \
- test/fuzz/blockheader_deserialize \
- test/fuzz/blocklocator_deserialize \
- test/fuzz/blockmerkleroot \
- test/fuzz/blocktransactions_deserialize \
- test/fuzz/blocktransactionsrequest_deserialize \
- test/fuzz/blockundo_deserialize \
- test/fuzz/bloom_filter \
- test/fuzz/bloomfilter_deserialize \
- test/fuzz/buffered_file \
- test/fuzz/chain \
- test/fuzz/checkqueue \
- test/fuzz/coins_deserialize \
- test/fuzz/coins_view \
- test/fuzz/crypto \
- test/fuzz/crypto_aes256 \
- test/fuzz/crypto_aes256cbc \
- test/fuzz/crypto_chacha20 \
- test/fuzz/crypto_chacha20_poly1305_aead \
- test/fuzz/crypto_common \
- test/fuzz/crypto_hkdf_hmac_sha256_l32 \
- test/fuzz/crypto_poly1305 \
- test/fuzz/cuckoocache \
- test/fuzz/decode_tx \
- test/fuzz/descriptor_parse \
- test/fuzz/diskblockindex_deserialize \
- test/fuzz/eval_script \
- test/fuzz/fee_rate \
- test/fuzz/fee_rate_deserialize \
- test/fuzz/fees \
- test/fuzz/flat_file_pos_deserialize \
- test/fuzz/flatfile \
- test/fuzz/float \
- test/fuzz/golomb_rice \
- test/fuzz/hex \
- test/fuzz/http_request \
- test/fuzz/integer \
- test/fuzz/inv_deserialize \
- test/fuzz/key \
- test/fuzz/key_io \
- test/fuzz/key_origin_info_deserialize \
- test/fuzz/kitchen_sink \
- test/fuzz/load_external_block_file \
- test/fuzz/locale \
- test/fuzz/merkle_block_deserialize \
- test/fuzz/merkleblock \
- test/fuzz/message \
- test/fuzz/messageheader_deserialize \
- test/fuzz/multiplication_overflow \
- test/fuzz/net \
- test/fuzz/net_permissions \
- test/fuzz/netaddr_deserialize \
- test/fuzz/netaddress \
- test/fuzz/out_point_deserialize \
- test/fuzz/p2p_transport_deserializer \
- test/fuzz/parse_hd_keypath \
- test/fuzz/parse_iso8601 \
- test/fuzz/parse_numbers \
- test/fuzz/parse_script \
- test/fuzz/parse_univalue \
- test/fuzz/partial_merkle_tree_deserialize \
- test/fuzz/partially_signed_transaction_deserialize \
- test/fuzz/policy_estimator \
- test/fuzz/policy_estimator_io \
- test/fuzz/pow \
- test/fuzz/prefilled_transaction_deserialize \
- test/fuzz/prevector \
- test/fuzz/primitives_transaction \
- test/fuzz/process_message \
- test/fuzz/process_message_addr \
- test/fuzz/process_message_block \
- test/fuzz/process_message_blocktxn \
- test/fuzz/process_message_cmpctblock \
- test/fuzz/process_message_feefilter \
- test/fuzz/process_message_filteradd \
- test/fuzz/process_message_filterclear \
- test/fuzz/process_message_filterload \
- test/fuzz/process_message_getaddr \
- test/fuzz/process_message_getblocks \
- test/fuzz/process_message_getblocktxn \
- test/fuzz/process_message_getdata \
- test/fuzz/process_message_getheaders \
- test/fuzz/process_message_headers \
- test/fuzz/process_message_inv \
- test/fuzz/process_message_mempool \
- test/fuzz/process_message_notfound \
- test/fuzz/process_message_ping \
- test/fuzz/process_message_pong \
- test/fuzz/process_message_sendcmpct \
- test/fuzz/process_message_sendheaders \
- test/fuzz/process_message_tx \
- test/fuzz/process_message_verack \
- test/fuzz/process_message_version \
- test/fuzz/process_messages \
- test/fuzz/protocol \
- test/fuzz/psbt \
- test/fuzz/psbt_input_deserialize \
- test/fuzz/psbt_output_deserialize \
- test/fuzz/pub_key_deserialize \
- test/fuzz/random \
- test/fuzz/rbf \
- test/fuzz/rolling_bloom_filter \
- test/fuzz/script \
- test/fuzz/script_bitcoin_consensus \
- test/fuzz/script_descriptor_cache \
- test/fuzz/script_deserialize \
- test/fuzz/script_flags \
- test/fuzz/script_interpreter \
- test/fuzz/script_assets_test_minimizer \
- test/fuzz/script_ops \
- test/fuzz/script_sigcache \
- test/fuzz/script_sign \
- test/fuzz/scriptnum_ops \
- test/fuzz/secp256k1_ec_seckey_import_export_der \
- test/fuzz/secp256k1_ecdsa_signature_parse_der_lax \
- test/fuzz/service_deserialize \
- test/fuzz/signature_checker \
- test/fuzz/signet \
- test/fuzz/snapshotmetadata_deserialize \
- test/fuzz/span \
- test/fuzz/spanparsing \
- test/fuzz/string \
- test/fuzz/strprintf \
- test/fuzz/sub_net_deserialize \
- test/fuzz/system \
- test/fuzz/timedata \
- test/fuzz/transaction \
- test/fuzz/tx_in \
- test/fuzz/tx_in_deserialize \
- test/fuzz/tx_out \
- test/fuzz/txoutcompressor_deserialize \
- test/fuzz/txrequest \
- test/fuzz/txundo_deserialize \
- test/fuzz/uint160_deserialize \
- test/fuzz/uint256_deserialize
-
if ENABLE_FUZZ
-noinst_PROGRAMS += $(FUZZ_TARGETS:=)
+noinst_PROGRAMS += test/fuzz/fuzz
else
bin_PROGRAMS += test/test_bitcoin
endif
TEST_SRCDIR = test
TEST_BINARY=test/test_bitcoin$(EXEEXT)
+FUZZ_BINARY=test/fuzz/fuzz$(EXEEXT)
JSON_TEST_FILES = \
test/data/script_tests.json \
@@ -290,15 +136,19 @@ BITCOIN_TESTS =\
if ENABLE_WALLET
BITCOIN_TESTS += \
- wallet/test/db_tests.cpp \
wallet/test/psbt_wallet_tests.cpp \
wallet/test/wallet_tests.cpp \
+ wallet/test/walletdb_tests.cpp \
wallet/test/wallet_crypto_tests.cpp \
wallet/test/coinselector_tests.cpp \
wallet/test/init_tests.cpp \
wallet/test/ismine_tests.cpp \
wallet/test/scriptpubkeyman_tests.cpp
+if USE_BDB
+BITCOIN_TESTS += wallet/test/db_tests.cpp
+endif
+
BITCOIN_TEST_SUITE += \
wallet/test/wallet_test_fixture.cpp \
wallet/test/wallet_test_fixture.h \
@@ -328,923 +178,103 @@ if ENABLE_FUZZ
FUZZ_SUITE_LDFLAGS_COMMON = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS)
-test_fuzz_addition_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_addition_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addition_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addition_overflow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addition_overflow_SOURCES = test/fuzz/addition_overflow.cpp
-
-test_fuzz_addr_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDR_INFO_DESERIALIZE=1
-test_fuzz_addr_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addr_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addr_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addr_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_addrdb_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_addrdb_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addrdb_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addrdb_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addrdb_SOURCES = test/fuzz/addrdb.cpp
-
-test_fuzz_address_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRESS_DESERIALIZE=1
-test_fuzz_address_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_address_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_address_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_address_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_addrman_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DADDRMAN_DESERIALIZE=1
-test_fuzz_addrman_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_addrman_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_addrman_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_addrman_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_asmap_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_asmap_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_asmap_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_asmap_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_asmap_SOURCES = test/fuzz/asmap.cpp
-
-test_fuzz_asmap_direct_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_asmap_direct_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_asmap_direct_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_asmap_direct_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_asmap_direct_SOURCES = test/fuzz/asmap_direct.cpp
-
-test_fuzz_autofile_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_autofile_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_autofile_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_autofile_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_autofile_SOURCES = test/fuzz/autofile.cpp
-
-test_fuzz_banentry_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBANENTRY_DESERIALIZE=1
-test_fuzz_banentry_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_banentry_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_banentry_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_banentry_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_banman_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_banman_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_banman_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_banman_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_banman_SOURCES = test/fuzz/banman.cpp
-
-test_fuzz_base_encode_decode_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_base_encode_decode_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_base_encode_decode_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_base_encode_decode_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_base_encode_decode_SOURCES = test/fuzz/base_encode_decode.cpp
-
-test_fuzz_bech32_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_bech32_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_bech32_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bech32_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_bech32_SOURCES = test/fuzz/bech32.cpp
-
-test_fuzz_block_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_block_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_SOURCES = test/fuzz/block.cpp
-
-test_fuzz_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_DESERIALIZE=1
-test_fuzz_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_block_file_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILE_INFO_DESERIALIZE=1
-test_fuzz_block_file_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_file_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_file_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_file_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_block_filter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_FILTER_DESERIALIZE=1
-test_fuzz_block_filter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_filter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_filter_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_filter_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_block_header_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_block_header_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_header_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_header_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_header_SOURCES = test/fuzz/block_header.cpp
-
-test_fuzz_block_header_and_short_txids_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE=1
-test_fuzz_block_header_and_short_txids_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_block_header_and_short_txids_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_block_header_and_short_txids_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_block_header_and_short_txids_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blockfilter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_blockfilter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockfilter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockfilter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockfilter_SOURCES = test/fuzz/blockfilter.cpp
-
-test_fuzz_blockheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKHEADER_DESERIALIZE=1
-test_fuzz_blockheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockheader_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockheader_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1
-test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blocklocator_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocklocator_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blocklocator_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blockmerkleroot_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKMERKLEROOT=1
-test_fuzz_blockmerkleroot_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockmerkleroot_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockmerkleroot_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockmerkleroot_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blocktransactions_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONS_DESERIALIZE=1
-test_fuzz_blocktransactions_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blocktransactions_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocktransactions_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blocktransactions_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blocktransactionsrequest_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKTRANSACTIONSREQUEST_DESERIALIZE=1
-test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blocktransactionsrequest_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_blockundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKUNDO_DESERIALIZE=1
-test_fuzz_blockundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_blockundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_blockundo_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_blockundo_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_bloom_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_bloom_filter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_bloom_filter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bloom_filter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_bloom_filter_SOURCES = test/fuzz/bloom_filter.cpp
-
-test_fuzz_bloomfilter_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOOMFILTER_DESERIALIZE=1
-test_fuzz_bloomfilter_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_bloomfilter_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_bloomfilter_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_bloomfilter_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_buffered_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_buffered_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_buffered_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_buffered_file_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_buffered_file_SOURCES = test/fuzz/buffered_file.cpp
-
-test_fuzz_chain_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_chain_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_chain_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_chain_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_chain_SOURCES = test/fuzz/chain.cpp
-
-test_fuzz_checkqueue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_checkqueue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_checkqueue_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_checkqueue_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_checkqueue_SOURCES = test/fuzz/checkqueue.cpp
-
-test_fuzz_coins_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DCOINS_DESERIALIZE=1
-test_fuzz_coins_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_coins_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_coins_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_coins_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_coins_view_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_coins_view_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_coins_view_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_coins_view_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_coins_view_SOURCES = test/fuzz/coins_view.cpp
-
-test_fuzz_crypto_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_SOURCES = test/fuzz/crypto.cpp
-
-test_fuzz_crypto_aes256_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_aes256_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_aes256_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_aes256_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_aes256_SOURCES = test/fuzz/crypto_aes256.cpp
-
-test_fuzz_crypto_aes256cbc_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_aes256cbc_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_aes256cbc_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_aes256cbc_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_aes256cbc_SOURCES = test/fuzz/crypto_aes256cbc.cpp
-
-test_fuzz_crypto_chacha20_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_chacha20_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_chacha20_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_chacha20_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_chacha20_SOURCES = test/fuzz/crypto_chacha20.cpp
-
-test_fuzz_crypto_chacha20_poly1305_aead_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_chacha20_poly1305_aead_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_chacha20_poly1305_aead_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_chacha20_poly1305_aead_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_chacha20_poly1305_aead_SOURCES = test/fuzz/crypto_chacha20_poly1305_aead.cpp
-
-test_fuzz_crypto_common_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_common_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_common_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_common_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_common_SOURCES = test/fuzz/crypto_common.cpp
-
-test_fuzz_crypto_hkdf_hmac_sha256_l32_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_hkdf_hmac_sha256_l32_SOURCES = test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
-
-test_fuzz_crypto_poly1305_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_crypto_poly1305_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_crypto_poly1305_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_crypto_poly1305_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_crypto_poly1305_SOURCES = test/fuzz/crypto_poly1305.cpp
-
-test_fuzz_cuckoocache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_cuckoocache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_cuckoocache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_cuckoocache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_cuckoocache_SOURCES = test/fuzz/cuckoocache.cpp
-
-test_fuzz_decode_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_decode_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_decode_tx_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_decode_tx_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_decode_tx_SOURCES = test/fuzz/decode_tx.cpp
-
-test_fuzz_descriptor_parse_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_descriptor_parse_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_descriptor_parse_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_descriptor_parse_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_descriptor_parse_SOURCES = test/fuzz/descriptor_parse.cpp
-
-test_fuzz_diskblockindex_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DDISKBLOCKINDEX_DESERIALIZE=1
-test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_diskblockindex_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_diskblockindex_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_eval_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_eval_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_eval_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_eval_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_eval_script_SOURCES = test/fuzz/eval_script.cpp
-
-test_fuzz_fee_rate_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_fee_rate_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_fee_rate_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fee_rate_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_fee_rate_SOURCES = test/fuzz/fee_rate.cpp
-
-test_fuzz_fee_rate_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFEE_RATE_DESERIALIZE=1
-test_fuzz_fee_rate_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_fee_rate_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fee_rate_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_fee_rate_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_fees_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_fees_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_fees_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_fees_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_fees_SOURCES = test/fuzz/fees.cpp
-
-test_fuzz_flat_file_pos_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DFLAT_FILE_POS_DESERIALIZE=1
-test_fuzz_flat_file_pos_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_flat_file_pos_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_flat_file_pos_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_flat_file_pos_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_flatfile_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_flatfile_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_flatfile_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_flatfile_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_flatfile_SOURCES = test/fuzz/flatfile.cpp
-
-test_fuzz_float_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_float_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_float_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_float_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_float_SOURCES = test/fuzz/float.cpp
-
-test_fuzz_golomb_rice_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_golomb_rice_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_golomb_rice_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_golomb_rice_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_golomb_rice_SOURCES = test/fuzz/golomb_rice.cpp
-
-test_fuzz_hex_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_hex_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_hex_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_hex_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_hex_SOURCES = test/fuzz/hex.cpp
-
-test_fuzz_http_request_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_http_request_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_http_request_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_http_request_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_http_request_SOURCES = test/fuzz/http_request.cpp
-
-test_fuzz_integer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_integer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_integer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_integer_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_integer_SOURCES = test/fuzz/integer.cpp
-
-test_fuzz_inv_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DINV_DESERIALIZE=1
-test_fuzz_inv_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_inv_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_inv_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_inv_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_key_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_key_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_key_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_key_SOURCES = test/fuzz/key.cpp
-
-test_fuzz_key_io_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_key_io_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_key_io_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_io_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_key_io_SOURCES = test/fuzz/key_io.cpp
-
-test_fuzz_key_origin_info_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DKEY_ORIGIN_INFO_DESERIALIZE=1
-test_fuzz_key_origin_info_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_key_origin_info_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_key_origin_info_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_key_origin_info_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_kitchen_sink_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_kitchen_sink_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_kitchen_sink_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_kitchen_sink_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_kitchen_sink_SOURCES = test/fuzz/kitchen_sink.cpp
-
-test_fuzz_load_external_block_file_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_load_external_block_file_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_load_external_block_file_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_load_external_block_file_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_load_external_block_file_SOURCES = test/fuzz/load_external_block_file.cpp
-
-test_fuzz_locale_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_locale_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_locale_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_locale_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_locale_SOURCES = test/fuzz/locale.cpp
-
-test_fuzz_merkle_block_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMERKLE_BLOCK_DESERIALIZE=1
-test_fuzz_merkle_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_merkle_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_merkle_block_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_merkle_block_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_merkleblock_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_merkleblock_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_merkleblock_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_merkleblock_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_merkleblock_SOURCES = test/fuzz/merkleblock.cpp
-
-test_fuzz_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_message_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_message_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_message_SOURCES = test/fuzz/message.cpp
-
-test_fuzz_messageheader_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGEHEADER_DESERIALIZE=1
-test_fuzz_messageheader_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_messageheader_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_messageheader_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_messageheader_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_multiplication_overflow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_multiplication_overflow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_multiplication_overflow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_multiplication_overflow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_multiplication_overflow_SOURCES = test/fuzz/multiplication_overflow.cpp
-
-test_fuzz_net_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_net_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_net_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_net_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_net_SOURCES = test/fuzz/net.cpp
-
-test_fuzz_net_permissions_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_net_permissions_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_net_permissions_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_net_permissions_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_net_permissions_SOURCES = test/fuzz/net_permissions.cpp
-
-test_fuzz_netaddr_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DNETADDR_DESERIALIZE=1
-test_fuzz_netaddr_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_netaddr_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_netaddr_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_netaddr_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_netaddress_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_netaddress_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_netaddress_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_netaddress_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_netaddress_SOURCES = test/fuzz/netaddress.cpp
-
-test_fuzz_out_point_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DOUT_POINT_DESERIALIZE=1
-test_fuzz_out_point_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_out_point_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_out_point_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_out_point_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_p2p_transport_deserializer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_p2p_transport_deserializer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_p2p_transport_deserializer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_p2p_transport_deserializer_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_p2p_transport_deserializer_SOURCES = test/fuzz/p2p_transport_deserializer.cpp
-
-test_fuzz_parse_hd_keypath_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_hd_keypath_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_hd_keypath_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_hd_keypath_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_hd_keypath_SOURCES = test/fuzz/parse_hd_keypath.cpp
-
-test_fuzz_parse_iso8601_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_iso8601_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_iso8601_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_iso8601_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_iso8601_SOURCES = test/fuzz/parse_iso8601.cpp
-
-test_fuzz_parse_numbers_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_numbers_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_numbers_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_numbers_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_numbers_SOURCES = test/fuzz/parse_numbers.cpp
-
-test_fuzz_parse_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_script_SOURCES = test/fuzz/parse_script.cpp
-
-test_fuzz_parse_univalue_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_parse_univalue_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_parse_univalue_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_parse_univalue_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_parse_univalue_SOURCES = test/fuzz/parse_univalue.cpp
-
-test_fuzz_prevector_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_prevector_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_prevector_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_prevector_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_prevector_SOURCES = test/fuzz/prevector.cpp
-
-test_fuzz_partial_merkle_tree_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIAL_MERKLE_TREE_DESERIALIZE=1
-test_fuzz_partial_merkle_tree_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_partial_merkle_tree_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_partial_merkle_tree_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_partial_merkle_tree_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_partially_signed_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPARTIALLY_SIGNED_TRANSACTION_DESERIALIZE=1
-test_fuzz_partially_signed_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_partially_signed_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_partially_signed_transaction_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_partially_signed_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_policy_estimator_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_policy_estimator_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_policy_estimator_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_policy_estimator_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_policy_estimator_SOURCES = test/fuzz/policy_estimator.cpp
-
-test_fuzz_policy_estimator_io_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_policy_estimator_io_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_policy_estimator_io_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_policy_estimator_io_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_policy_estimator_io_SOURCES = test/fuzz/policy_estimator_io.cpp
-
-test_fuzz_pow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_pow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_pow_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_pow_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_pow_SOURCES = test/fuzz/pow.cpp
-
-test_fuzz_prefilled_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPREFILLED_TRANSACTION_DESERIALIZE=1
-test_fuzz_prefilled_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_prefilled_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_prefilled_transaction_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_prefilled_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_primitives_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_primitives_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_primitives_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_primitives_transaction_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_primitives_transaction_SOURCES = test/fuzz/primitives_transaction.cpp
-
-test_fuzz_process_messages_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_process_messages_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_messages_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_messages_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_messages_SOURCES = test/fuzz/process_messages.cpp
-
-test_fuzz_process_message_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_process_message_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_addr_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=addr
-test_fuzz_process_message_addr_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_addr_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_addr_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_addr_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_block_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=block
-test_fuzz_process_message_block_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_block_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_block_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_block_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_blocktxn_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=blocktxn
-test_fuzz_process_message_blocktxn_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_blocktxn_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_blocktxn_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_blocktxn_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_cmpctblock_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=cmpctblock
-test_fuzz_process_message_cmpctblock_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_cmpctblock_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_cmpctblock_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_cmpctblock_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_feefilter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=feefilter
-test_fuzz_process_message_feefilter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_feefilter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_feefilter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_feefilter_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_filteradd_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filteradd
-test_fuzz_process_message_filteradd_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_filteradd_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filteradd_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_filteradd_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_filterclear_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filterclear
-test_fuzz_process_message_filterclear_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_filterclear_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filterclear_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_filterclear_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_filterload_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=filterload
-test_fuzz_process_message_filterload_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_filterload_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_filterload_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_filterload_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getaddr_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getaddr
-test_fuzz_process_message_getaddr_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getaddr_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getaddr_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getaddr_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getblocks_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getblocks
-test_fuzz_process_message_getblocks_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getblocks_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getblocks_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getblocks_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getblocktxn_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getblocktxn
-test_fuzz_process_message_getblocktxn_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getblocktxn_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getblocktxn_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getblocktxn_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getdata_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getdata
-test_fuzz_process_message_getdata_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getdata_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getdata_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getdata_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_getheaders_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=getheaders
-test_fuzz_process_message_getheaders_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_getheaders_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_getheaders_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_getheaders_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_headers_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=headers
-test_fuzz_process_message_headers_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_headers_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_headers_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_headers_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_inv_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=inv
-test_fuzz_process_message_inv_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_inv_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_inv_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_inv_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_mempool_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=mempool
-test_fuzz_process_message_mempool_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_mempool_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_mempool_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_mempool_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_notfound_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=notfound
-test_fuzz_process_message_notfound_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_notfound_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_notfound_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_notfound_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_ping_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=ping
-test_fuzz_process_message_ping_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_ping_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_ping_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_ping_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_pong_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=pong
-test_fuzz_process_message_pong_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_pong_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_pong_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_pong_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_sendcmpct_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=sendcmpct
-test_fuzz_process_message_sendcmpct_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_sendcmpct_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_sendcmpct_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_sendcmpct_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_sendheaders_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=sendheaders
-test_fuzz_process_message_sendheaders_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_sendheaders_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_sendheaders_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_sendheaders_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=tx
-test_fuzz_process_message_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_tx_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_tx_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_tx_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_verack_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=verack
-test_fuzz_process_message_verack_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_verack_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_verack_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_verack_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_process_message_version_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMESSAGE_TYPE=version
-test_fuzz_process_message_version_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_process_message_version_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_process_message_version_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_process_message_version_SOURCES = test/fuzz/process_message.cpp
-
-test_fuzz_protocol_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_protocol_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_protocol_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_protocol_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_protocol_SOURCES = test/fuzz/protocol.cpp
-
-test_fuzz_psbt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_psbt_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_psbt_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_psbt_SOURCES = test/fuzz/psbt.cpp
-
-test_fuzz_psbt_input_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_INPUT_DESERIALIZE=1
-test_fuzz_psbt_input_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_psbt_input_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_input_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_psbt_input_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_psbt_output_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPSBT_OUTPUT_DESERIALIZE=1
-test_fuzz_psbt_output_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_psbt_output_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_psbt_output_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_psbt_output_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_pub_key_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DPUB_KEY_DESERIALIZE=1
-test_fuzz_pub_key_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_pub_key_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_pub_key_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_pub_key_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_random_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_random_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_random_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_random_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_random_SOURCES = test/fuzz/random.cpp
-
-test_fuzz_rbf_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_rbf_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_rbf_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_rbf_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_rbf_SOURCES = test/fuzz/rbf.cpp
-
-test_fuzz_rolling_bloom_filter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_rolling_bloom_filter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_rolling_bloom_filter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_rolling_bloom_filter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_rolling_bloom_filter_SOURCES = test/fuzz/rolling_bloom_filter.cpp
-
-test_fuzz_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_SOURCES = test/fuzz/script.cpp
-
-test_fuzz_script_bitcoin_consensus_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_bitcoin_consensus_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_bitcoin_consensus_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_bitcoin_consensus_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_bitcoin_consensus_SOURCES = test/fuzz/script_bitcoin_consensus.cpp
-
-test_fuzz_script_descriptor_cache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_descriptor_cache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_descriptor_cache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_descriptor_cache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_descriptor_cache_SOURCES = test/fuzz/script_descriptor_cache.cpp
-
-test_fuzz_script_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSCRIPT_DESERIALIZE=1
-test_fuzz_script_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_script_flags_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_flags_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_flags_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_flags_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_flags_SOURCES = test/fuzz/script_flags.cpp
-
-test_fuzz_script_interpreter_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_interpreter_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_interpreter_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_interpreter_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_interpreter_SOURCES = test/fuzz/script_interpreter.cpp
-
-test_fuzz_script_assets_test_minimizer_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_assets_test_minimizer_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_assets_test_minimizer_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_assets_test_minimizer_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_script_assets_test_minimizer_SOURCES = test/fuzz/script_assets_test_minimizer.cpp
-
-test_fuzz_script_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_ops_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_ops_SOURCES = test/fuzz/script_ops.cpp
-
-test_fuzz_script_sigcache_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_sigcache_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_sigcache_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_sigcache_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_sigcache_SOURCES = test/fuzz/script_sigcache.cpp
-
-test_fuzz_script_sign_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_script_sign_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_script_sign_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_script_sign_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_script_sign_SOURCES = test/fuzz/script_sign.cpp
-
-test_fuzz_scriptnum_ops_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_scriptnum_ops_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_scriptnum_ops_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_scriptnum_ops_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_scriptnum_ops_SOURCES = test/fuzz/scriptnum_ops.cpp
-
-test_fuzz_secp256k1_ec_seckey_import_export_der_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_secp256k1_ec_seckey_import_export_der_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_secp256k1_ec_seckey_import_export_der_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_secp256k1_ec_seckey_import_export_der_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_secp256k1_ec_seckey_import_export_der_SOURCES = test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
-
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_secp256k1_ecdsa_signature_parse_der_lax_SOURCES = test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
-
-test_fuzz_service_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSERVICE_DESERIALIZE=1
-test_fuzz_service_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_service_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_service_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_service_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_signature_checker_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_signature_checker_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_signature_checker_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_signature_checker_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_signature_checker_SOURCES = test/fuzz/signature_checker.cpp
-
-test_fuzz_signet_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_signet_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_signet_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_signet_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
-test_fuzz_signet_SOURCES = test/fuzz/signet.cpp
-
-test_fuzz_snapshotmetadata_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSNAPSHOTMETADATA_DESERIALIZE=1
-test_fuzz_snapshotmetadata_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_snapshotmetadata_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_snapshotmetadata_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_snapshotmetadata_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_span_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_span_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_span_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_span_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_span_SOURCES = test/fuzz/span.cpp
-
-test_fuzz_spanparsing_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_spanparsing_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_spanparsing_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_spanparsing_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_spanparsing_SOURCES = test/fuzz/spanparsing.cpp
-
-test_fuzz_string_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_string_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_string_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_string_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_string_SOURCES = test/fuzz/string.cpp
-
-test_fuzz_strprintf_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_strprintf_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_strprintf_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_strprintf_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_strprintf_SOURCES = test/fuzz/strprintf.cpp
-
-test_fuzz_sub_net_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DSUB_NET_DESERIALIZE=1
-test_fuzz_sub_net_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_sub_net_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_sub_net_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_sub_net_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_system_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_system_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_system_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_system_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_system_SOURCES = test/fuzz/system.cpp
-
-test_fuzz_timedata_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_timedata_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_timedata_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_timedata_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_timedata_SOURCES = test/fuzz/timedata.cpp
-
-test_fuzz_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_transaction_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_transaction_SOURCES = test/fuzz/transaction.cpp
-
-test_fuzz_tx_in_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_tx_in_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_tx_in_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_in_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_tx_in_SOURCES = test/fuzz/tx_in.cpp
-
-test_fuzz_tx_in_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTX_IN_DESERIALIZE=1
-test_fuzz_tx_in_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_tx_in_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_in_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_tx_in_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_tx_out_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_tx_out_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_tx_out_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_tx_out_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_tx_out_SOURCES = test/fuzz/tx_out.cpp
-
-test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1
-test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_txoutcompressor_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txoutcompressor_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_txoutcompressor_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_txrequest_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
-test_fuzz_txrequest_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_txrequest_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txrequest_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_txrequest_SOURCES = test/fuzz/txrequest.cpp
-
-test_fuzz_txundo_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXUNDO_DESERIALIZE=1
-test_fuzz_txundo_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_txundo_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_txundo_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_txundo_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_uint160_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT160_DESERIALIZE=1
-test_fuzz_uint160_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_uint160_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_uint160_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_uint160_deserialize_SOURCES = test/fuzz/deserialize.cpp
-
-test_fuzz_uint256_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DUINT256_DESERIALIZE=1
-test_fuzz_uint256_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
-test_fuzz_uint256_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON)
-test_fuzz_uint256_deserialize_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
-test_fuzz_uint256_deserialize_SOURCES = test/fuzz/deserialize.cpp
+test_fuzz_fuzz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
+test_fuzz_fuzz_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+test_fuzz_fuzz_LDADD = $(FUZZ_SUITE_LD_COMMON)
+test_fuzz_fuzz_LDFLAGS = $(FUZZ_SUITE_LDFLAGS_COMMON)
+test_fuzz_fuzz_SOURCES = \
+ test/fuzz/addition_overflow.cpp \
+ test/fuzz/addrdb.cpp \
+ test/fuzz/addrman.cpp \
+ test/fuzz/asmap.cpp \
+ test/fuzz/asmap_direct.cpp \
+ test/fuzz/autofile.cpp \
+ test/fuzz/banman.cpp \
+ test/fuzz/base_encode_decode.cpp \
+ test/fuzz/bech32.cpp \
+ test/fuzz/block.cpp \
+ test/fuzz/block_header.cpp \
+ test/fuzz/blockfilter.cpp \
+ test/fuzz/bloom_filter.cpp \
+ test/fuzz/buffered_file.cpp \
+ test/fuzz/chain.cpp \
+ test/fuzz/checkqueue.cpp \
+ test/fuzz/coins_view.cpp \
+ test/fuzz/connman.cpp \
+ test/fuzz/crypto.cpp \
+ test/fuzz/crypto_aes256.cpp \
+ test/fuzz/crypto_aes256cbc.cpp \
+ test/fuzz/crypto_chacha20.cpp \
+ test/fuzz/crypto_chacha20_poly1305_aead.cpp \
+ test/fuzz/crypto_common.cpp \
+ test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp \
+ test/fuzz/crypto_poly1305.cpp \
+ test/fuzz/cuckoocache.cpp \
+ test/fuzz/decode_tx.cpp \
+ test/fuzz/descriptor_parse.cpp \
+ test/fuzz/deserialize.cpp \
+ test/fuzz/eval_script.cpp \
+ test/fuzz/fee_rate.cpp \
+ test/fuzz/fees.cpp \
+ test/fuzz/flatfile.cpp \
+ test/fuzz/float.cpp \
+ test/fuzz/golomb_rice.cpp \
+ test/fuzz/hex.cpp \
+ test/fuzz/http_request.cpp \
+ test/fuzz/integer.cpp \
+ test/fuzz/key.cpp \
+ test/fuzz/key_io.cpp \
+ test/fuzz/kitchen_sink.cpp \
+ test/fuzz/load_external_block_file.cpp \
+ test/fuzz/locale.cpp \
+ test/fuzz/merkleblock.cpp \
+ test/fuzz/message.cpp \
+ test/fuzz/multiplication_overflow.cpp \
+ test/fuzz/net.cpp \
+ test/fuzz/net_permissions.cpp \
+ test/fuzz/netaddress.cpp \
+ test/fuzz/p2p_transport_deserializer.cpp \
+ test/fuzz/parse_hd_keypath.cpp \
+ test/fuzz/parse_iso8601.cpp \
+ test/fuzz/parse_numbers.cpp \
+ test/fuzz/parse_script.cpp \
+ test/fuzz/parse_univalue.cpp \
+ test/fuzz/policy_estimator.cpp \
+ test/fuzz/policy_estimator_io.cpp \
+ test/fuzz/pow.cpp \
+ test/fuzz/prevector.cpp \
+ test/fuzz/primitives_transaction.cpp \
+ test/fuzz/process_message.cpp \
+ test/fuzz/process_messages.cpp \
+ test/fuzz/protocol.cpp \
+ test/fuzz/psbt.cpp \
+ test/fuzz/random.cpp \
+ test/fuzz/rbf.cpp \
+ test/fuzz/rolling_bloom_filter.cpp \
+ test/fuzz/script.cpp \
+ test/fuzz/script_assets_test_minimizer.cpp \
+ test/fuzz/script_bitcoin_consensus.cpp \
+ test/fuzz/script_descriptor_cache.cpp \
+ test/fuzz/script_flags.cpp \
+ test/fuzz/script_interpreter.cpp \
+ test/fuzz/script_ops.cpp \
+ test/fuzz/script_sigcache.cpp \
+ test/fuzz/script_sign.cpp \
+ test/fuzz/scriptnum_ops.cpp \
+ test/fuzz/secp256k1_ec_seckey_import_export_der.cpp \
+ test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp \
+ test/fuzz/signature_checker.cpp \
+ test/fuzz/signet.cpp \
+ test/fuzz/span.cpp \
+ test/fuzz/spanparsing.cpp \
+ test/fuzz/string.cpp \
+ test/fuzz/strprintf.cpp \
+ test/fuzz/system.cpp \
+ test/fuzz/timedata.cpp \
+ test/fuzz/transaction.cpp \
+ test/fuzz/tx_in.cpp \
+ test/fuzz/tx_out.cpp \
+ test/fuzz/txrequest.cpp
endif # ENABLE_FUZZ
@@ -1291,6 +321,11 @@ if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
endif
+if ENABLE_FUZZ_LINK_ALL
+all-local: $(FUZZ_BINARY)
+ bash ./test/fuzz/danger_link_all.sh
+endif
+
%.cpp.test: %.cpp
@echo Running tests: `cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1` from $<
$(AM_V_at)$(TEST_BINARY) --catch_system_errors=no -l test_suite -t "`cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" -- DEBUG_LOG_OUT > $<.log 2>&1 || (cat $<.log && false)
diff --git a/src/Makefile.test_util.include b/src/Makefile.test_util.include
index d7bc73defb..0621da8ddf 100644
--- a/src/Makefile.test_util.include
+++ b/src/Makefile.test_util.include
@@ -15,6 +15,7 @@ TEST_UTIL_H = \
test/util/setup_common.h \
test/util/str.h \
test/util/transaction_utils.h \
+ test/util/validation.h \
test/util/wallet.h
libtest_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
@@ -27,6 +28,7 @@ libtest_util_a_SOURCES = \
test/util/setup_common.cpp \
test/util/str.cpp \
test/util/transaction_utils.cpp \
+ test/util/validation.cpp \
test/util/wallet.cpp \
$(TEST_UTIL_H)
diff --git a/src/addrdb.cpp b/src/addrdb.cpp
index f3e8a19de2..27f22826a9 100644
--- a/src/addrdb.cpp
+++ b/src/addrdb.cpp
@@ -10,6 +10,7 @@
#include <clientversion.h>
#include <cstdint>
#include <hash.h>
+#include <logging/timer.h>
#include <random.h>
#include <streams.h>
#include <tinyformat.h>
@@ -156,3 +157,22 @@ bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
}
return ret;
}
+
+void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors)
+{
+ LOG_TIME_SECONDS(strprintf("Flush %d outbound block-relay-only peer addresses to anchors.dat", anchors.size()));
+ SerializeFileDB("anchors", anchors_db_path, anchors);
+}
+
+std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path)
+{
+ std::vector<CAddress> anchors;
+ if (DeserializeFileDB(anchors_db_path, anchors)) {
+ LogPrintf("Loaded %i addresses from %s\n", anchors.size(), anchors_db_path.filename());
+ } else {
+ anchors.clear();
+ }
+
+ fs::remove(anchors_db_path);
+ return anchors;
+}
diff --git a/src/addrdb.h b/src/addrdb.h
index 8410c3776c..4ac0e3e1b5 100644
--- a/src/addrdb.h
+++ b/src/addrdb.h
@@ -11,9 +11,9 @@
#include <serialize.h>
#include <string>
-#include <map>
+#include <vector>
-class CSubNet;
+class CAddress;
class CAddrMan;
class CDataStream;
@@ -73,4 +73,20 @@ public:
bool Read(banmap_t& banSet);
};
+/**
+ * Dump the anchor IP address database (anchors.dat)
+ *
+ * Anchors are last known outgoing block-relay-only peers that are
+ * tried to re-connect to on startup.
+ */
+void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors);
+
+/**
+ * Read the anchor IP address database (anchors.dat)
+ *
+ * Deleting anchors.dat is intentional as it avoids renewed peering to anchors after
+ * an unclean shutdown and thus potential exploitation of the anchor peer policy.
+ */
+std::vector<CAddress> ReadAnchors(const fs::path& anchors_db_path);
+
#endif // BITCOIN_ADDRDB_H
diff --git a/src/addrman.h b/src/addrman.h
index b4089dc894..9ac67b7af6 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -7,6 +7,7 @@
#define BITCOIN_ADDRMAN_H
#include <clientversion.h>
+#include <config/bitcoin-config.h>
#include <netaddress.h>
#include <protocol.h>
#include <random.h>
@@ -176,6 +177,28 @@ protected:
mutable RecursiveMutex cs;
private:
+ //! Serialization versions.
+ enum Format : uint8_t {
+ V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
+ V1_DETERMINISTIC = 1, //!< for pre-asmap files
+ V2_ASMAP = 2, //!< for files including asmap version
+ V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format
+ };
+
+ //! The maximum format this software knows it can unserialize. Also, we always serialize
+ //! in this format.
+ //! The format (first byte in the serialized stream) can be higher than this and
+ //! still this software may be able to unserialize the file - if the second byte
+ //! (see `lowest_compatible` in `Unserialize()`) is less or equal to this.
+ static constexpr Format FILE_FORMAT = Format::V3_BIP155;
+
+ //! The initial value of a field that is incremented every time an incompatible format
+ //! change is made (such that old software versions would not be able to parse and
+ //! understand the new file format). This is 32 because we overtook the "key size"
+ //! field which was 32 historically.
+ //! @note Don't increment this. Increment `lowest_compatible` in `Serialize()` instead.
+ static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
+
//! last used nId
int nIdCount GUARDED_BY(cs);
@@ -258,21 +281,23 @@ protected:
//! Select several addresses at once.
void GetAddr_(std::vector<CAddress> &vAddr, size_t max_addresses, size_t max_pct) EXCLUSIVE_LOCKS_REQUIRED(cs);
- //! Mark an entry as currently-connected-to.
- void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
+ /** We have successfully connected to this peer. Calling this function
+ * updates the CAddress's nTime, which is used in our IsTerrible()
+ * decisions and gossiped to peers. Callers should be careful that updating
+ * this information doesn't leak topology information to network spies.
+ *
+ * net_processing calls this function when it *disconnects* from a peer to
+ * 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
+ */
+ void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Update an entry's service bits.
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
- //! Serialization versions.
- enum class Format : uint8_t {
- V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
- V1_DETERMINISTIC = 1, //!< for pre-asmap files
- V2_ASMAP = 2, //!< for files including asmap version
- V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format
- };
-
// Compressed IP->ASN mapping, loaded from a file when a node starts.
// Should be always empty if no file was provided.
// This mapping is then used for bucketing nodes in Addrman.
@@ -295,8 +320,18 @@ public:
/**
* Serialized format.
- * * version byte (@see `Format`)
- * * 0x20 + nKey (serialized as if it were a vector, for backward compatibility)
+ * * format version byte (@see `Format`)
+ * * lowest compatible format version byte. This is used to help old software decide
+ * whether to parse the file. For example:
+ * * Bitcoin Core version N knows how to parse up to format=3. If a new format=4 is
+ * introduced in version N+1 that is compatible with format=3 and it is known that
+ * version N will be able to parse it, then version N+1 will write
+ * (format=4, lowest_compatible=3) in the first two bytes of the file, and so
+ * version N will still try to parse it.
+ * * Bitcoin Core version N+2 introduces a new incompatible format=5. It will write
+ * (format=5, lowest_compatible=5) and so any versions that do not know how to parse
+ * format=5 will not try to read the file.
+ * * nKey
* * nNew
* * nTried
* * number of "new" buckets XOR 2**30
@@ -327,12 +362,17 @@ public:
{
LOCK(cs);
- // Always serialize in the latest version (currently Format::V3_BIP155).
+ // Always serialize in the latest version (FILE_FORMAT).
OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT);
- s << static_cast<uint8_t>(Format::V3_BIP155);
- s << ((unsigned char)32);
+ s << static_cast<uint8_t>(FILE_FORMAT);
+
+ // Increment `lowest_compatible` iff a newly introduced format is incompatible with
+ // the previous one.
+ static constexpr uint8_t lowest_compatible = Format::V3_BIP155;
+ s << static_cast<uint8_t>(INCOMPATIBILITY_BASE + lowest_compatible);
+
s << nKey;
s << nNew;
s << nTried;
@@ -392,15 +432,6 @@ public:
Format format;
s_ >> Using<CustomUintFormatter<1>>(format);
- static constexpr Format maximum_supported_format = Format::V3_BIP155;
- if (format > maximum_supported_format) {
- throw std::ios_base::failure(strprintf(
- "Unsupported format of addrman database: %u. Maximum supported is %u. "
- "Continuing operation without using the saved list of peers.",
- static_cast<uint8_t>(format),
- static_cast<uint8_t>(maximum_supported_format)));
- }
-
int stream_version = s_.GetVersion();
if (format >= Format::V3_BIP155) {
// Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
@@ -410,9 +441,16 @@ public:
OverrideStream<Stream> s(&s_, s_.GetType(), stream_version);
- unsigned char nKeySize;
- s >> nKeySize;
- if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization");
+ uint8_t compat;
+ s >> compat;
+ const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE;
+ if (lowest_compatible > FILE_FORMAT) {
+ throw std::ios_base::failure(strprintf(
+ "Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
+ "but the maximum supported by this version of %s is %u.",
+ format, lowest_compatible, PACKAGE_NAME, static_cast<uint8_t>(FILE_FORMAT)));
+ }
+
s >> nKey;
s >> nNew;
s >> nTried;
@@ -676,7 +714,7 @@ public:
return vAddr;
}
- //! Mark an entry as currently-connected-to.
+ //! Outer function for Connected_()
void Connected(const CService &addr, int64_t nTime = GetAdjustedTime())
{
LOCK(cs);
diff --git a/src/attributes.h b/src/attributes.h
index 45099bd8b8..995c24e13f 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -6,17 +6,14 @@
#ifndef BITCOIN_ATTRIBUTES_H
#define BITCOIN_ATTRIBUTES_H
-#if defined(__has_cpp_attribute)
-# if __has_cpp_attribute(nodiscard)
-# define NODISCARD [[nodiscard]]
-# endif
-#endif
-#ifndef NODISCARD
-# if defined(_MSC_VER) && _MSC_VER >= 1700
-# define NODISCARD _Check_return_
+#if defined(__clang__)
+# if __has_attribute(lifetimebound)
+# define LIFETIMEBOUND [[clang::lifetimebound]]
# else
-# define NODISCARD __attribute__((warn_unused_result))
+# define LIFETIMEBOUND
# endif
+#else
+# define LIFETIMEBOUND
#endif
#endif // BITCOIN_ATTRIBUTES_H
diff --git a/src/base58.cpp b/src/base58.cpp
index 0dc6044145..780846c6c5 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -35,7 +35,7 @@ static const int8_t mapBase58[256] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
};
-NODISCARD static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
+[[nodiscard]] static bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_len)
{
// Skip leading spaces.
while (*psz && IsSpace(*psz))
@@ -141,7 +141,7 @@ std::string EncodeBase58Check(Span<const unsigned char> input)
return EncodeBase58(vch);
}
-NODISCARD static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
+[[nodiscard]] static bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet, int max_ret_len)
{
if (!DecodeBase58(psz, vchRet, max_ret_len > std::numeric_limits<int>::max() - 4 ? std::numeric_limits<int>::max() : max_ret_len + 4) ||
(vchRet.size() < 4)) {
diff --git a/src/base58.h b/src/base58.h
index 468c3e2589..60551a12ae 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -29,7 +29,7 @@ std::string EncodeBase58(Span<const unsigned char> input);
* Decode a base58-encoded string (str) into a byte vector (vchRet).
* return true if decoding is successful.
*/
-NODISCARD bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len);
+[[nodiscard]] bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len);
/**
* Encode a byte span into a base58-encoded string, including checksum
@@ -40,6 +40,6 @@ std::string EncodeBase58Check(Span<const unsigned char> input);
* Decode a base58-encoded string (str) that includes a checksum into a byte
* vector (vchRet), return true if decoding is successful
*/
-NODISCARD bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len);
+[[nodiscard]] bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len);
#endif // BITCOIN_BASE58_H
diff --git a/src/bench/ccoins_caching.cpp b/src/bench/ccoins_caching.cpp
index 116de98b14..d5275b0b76 100644
--- a/src/bench/ccoins_caching.cpp
+++ b/src/bench/ccoins_caching.cpp
@@ -45,7 +45,7 @@ static void CCoinsCaching(benchmark::Bench& bench)
// Benchmark.
const CTransaction tx_1(t1);
bench.run([&] {
- bool success = AreInputsStandard(tx_1, coins);
+ bool success = AreInputsStandard(tx_1, coins, false);
assert(success);
});
ECC_Stop();
diff --git a/src/bench/chacha_poly_aead.cpp b/src/bench/chacha_poly_aead.cpp
index 3b1d3e697a..e994279a4d 100644
--- a/src/bench/chacha_poly_aead.cpp
+++ b/src/bench/chacha_poly_aead.cpp
@@ -31,12 +31,15 @@ static void CHACHA20_POLY1305_AEAD(benchmark::Bench& bench, size_t buffersize, b
uint32_t len = 0;
bench.batch(buffersize).unit("byte").run([&] {
// encrypt or decrypt the buffer with a static key
- assert(aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true));
+ const bool crypt_ok_1 = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true);
+ assert(crypt_ok_1);
if (include_decryption) {
// if we decrypt, include the GetLength
- assert(aead.GetLength(&len, seqnr_aad, aad_pos, in.data()));
- assert(aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true));
+ const bool get_length_ok = aead.GetLength(&len, seqnr_aad, aad_pos, in.data());
+ assert(get_length_ok);
+ const bool crypt_ok_2 = aead.Crypt(seqnr_payload, seqnr_aad, aad_pos, out.data(), out.size(), in.data(), buffersize, true);
+ assert(crypt_ok_2);
}
// increase main sequence number
diff --git a/src/bench/prevector.cpp b/src/bench/prevector.cpp
index a2dbefa54a..73af244ce0 100644
--- a/src/bench/prevector.cpp
+++ b/src/bench/prevector.cpp
@@ -9,24 +9,16 @@
#include <bench/bench.h>
-// GCC 4.8 is missing some C++11 type_traits,
-// https://www.gnu.org/software/gcc/gcc-5/changes.html
-#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
-#define IS_TRIVIALLY_CONSTRUCTIBLE std::has_trivial_default_constructor
-#else
-#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivially_default_constructible
-#endif
-
struct nontrivial_t {
int x;
nontrivial_t() :x(-1) {}
SERIALIZE_METHODS(nontrivial_t, obj) { READWRITE(obj.x); }
};
-static_assert(!IS_TRIVIALLY_CONSTRUCTIBLE<nontrivial_t>::value,
+static_assert(!std::is_trivially_default_constructible<nontrivial_t>::value,
"expected nontrivial_t to not be trivially constructible");
typedef unsigned char trivial_t;
-static_assert(IS_TRIVIALLY_CONSTRUCTIBLE<trivial_t>::value,
+static_assert(std::is_trivially_default_constructible<trivial_t>::value,
"expected trivial_t to be trivially constructible");
template <typename T>
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index b3b73284d8..aa436ee3ea 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -24,15 +24,13 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
- CWallet wallet{chain.get(), "", CreateMockWalletDatabase()};
+ CWallet wallet{test_setup.m_node.chain.get(), "", CreateMockWalletDatabase()};
{
wallet.SetupLegacyScriptPubKeyMan();
bool first_run;
if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
}
- auto handler = chain->handleNotifications({&wallet, [](CWallet*) {}});
+ auto handler = test_setup.m_node.chain->handleNotifications({&wallet, [](CWallet*) {}});
const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc
index 58f8f1e8a2..405a302261 100644
--- a/src/bitcoin-cli-res.rc
+++ b/src/bitcoin-cli-res.rc
@@ -1,8 +1,8 @@
#include <windows.h> // needed for VERSIONINFO
#include "clientversion.h" // holds the needed client version information
-#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
-#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD
+#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD)
#define VER_FILEVERSION VER_PRODUCTVERSION
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 28394e7041..ef4641cb63 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -14,11 +14,13 @@
#include <rpc/mining.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
+#include <tinyformat.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <util/url.h>
+#include <algorithm>
#include <functional>
#include <memory>
#include <stdio.h>
@@ -39,8 +41,6 @@ static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
static const bool DEFAULT_NAMED=false;
static const int CONTINUE_EXECUTION=-1;
-static const std::string ONION{".onion"};
-static const size_t ONION_LEN{ONION.size()};
/** Default number of blocks to generate for RPC generatetoaddress. */
static const std::string DEFAULT_NBLOCKS = "1";
@@ -298,66 +298,62 @@ public:
class NetinfoRequestHandler : public BaseRequestHandler
{
private:
- bool IsAddrIPv6(const std::string& addr) const
+ static constexpr int8_t UNKNOWN_NETWORK{-1};
+ static constexpr uint8_t m_networks_size{3};
+ const std::array<std::string, m_networks_size> m_networks{{"ipv4", "ipv6", "onion"}};
+ std::array<std::array<uint16_t, m_networks_size + 2>, 3> m_counts{{{}}}; //!< Peer counts by (in/out/total, networks/total/block-relay)
+ int8_t NetworkStringToId(const std::string& str) const
{
- return !addr.empty() && addr.front() == '[';
- }
- bool IsInboundOnion(const std::string& addr_local, int mapped_as) const
- {
- return mapped_as == 0 && addr_local.find(ONION) != std::string::npos;
- }
- bool IsOutboundOnion(const std::string& addr, int mapped_as) const
- {
- const size_t addr_len{addr.size()};
- const size_t onion_pos{addr.rfind(ONION)};
- return mapped_as == 0 && onion_pos != std::string::npos && addr_len > ONION_LEN &&
- (onion_pos == addr_len - ONION_LEN || onion_pos == addr.find_last_of(":") - ONION_LEN);
+ for (uint8_t i = 0; i < m_networks_size; ++i) {
+ if (str == m_networks.at(i)) return i;
+ }
+ return UNKNOWN_NETWORK;
}
uint8_t m_details_level{0}; //!< Optional user-supplied arg to set dashboard details level
bool DetailsRequested() const { return m_details_level > 0 && m_details_level < 5; }
bool IsAddressSelected() const { return m_details_level == 2 || m_details_level == 4; }
bool IsVersionSelected() const { return m_details_level == 3 || m_details_level == 4; }
- enum struct NetType {
- ipv4,
- ipv6,
- onion,
- };
+ bool m_is_asmap_on{false};
+ size_t m_max_addr_length{0};
+ size_t m_max_age_length{4};
+ size_t m_max_id_length{2};
struct Peer {
- int id;
- int mapped_as;
- int version;
- int64_t conn_time;
+ std::string addr;
+ std::string sub_version;
+ std::string network;
+ std::string age;
+ double min_ping;
+ double ping;
int64_t last_blck;
int64_t last_recv;
int64_t last_send;
int64_t last_trxn;
- double min_ping;
- double ping;
- std::string addr;
- std::string sub_version;
- NetType net_type;
+ int id;
+ int mapped_as;
+ int version;
bool is_block_relay;
bool is_outbound;
bool operator<(const Peer& rhs) const { return std::tie(is_outbound, min_ping) < std::tie(rhs.is_outbound, rhs.min_ping); }
};
- std::string NetTypeEnumToString(NetType t)
- {
- switch (t) {
- case NetType::ipv4: return "ipv4";
- case NetType::ipv6: return "ipv6";
- case NetType::onion: return "onion";
- } // no default case, so the compiler can warn about missing cases
- assert(false);
- }
+ std::vector<Peer> m_peers;
std::string ChainToString() const
{
if (gArgs.GetChainName() == CBaseChainParams::TESTNET) return " testnet";
+ if (gArgs.GetChainName() == CBaseChainParams::SIGNET) return " signet";
if (gArgs.GetChainName() == CBaseChainParams::REGTEST) return " regtest";
return "";
}
+ std::string PingTimeToString(double seconds) const
+ {
+ if (seconds < 0) return "";
+ const double milliseconds{round(1000 * seconds)};
+ return milliseconds > 999999 ? "-" : ToString(milliseconds);
+ }
+ const int64_t m_time_now{GetSystemTimeInSeconds()};
+
public:
- const int ID_PEERINFO = 0;
- const int ID_NETWORKINFO = 1;
+ static constexpr int ID_PEERINFO = 0;
+ static constexpr int ID_NETWORKINFO = 1;
UniValue PrepareRequest(const std::string& method, const std::vector<std::string>& args) override
{
@@ -385,49 +381,25 @@ public:
}
// Count peer connection totals, and if DetailsRequested(), store peer data in a vector of structs.
- const int64_t time_now{GetSystemTimeInSeconds()};
- int ipv4_i{0}, ipv6_i{0}, onion_i{0}, block_relay_i{0}, total_i{0}; // inbound conn counters
- int ipv4_o{0}, ipv6_o{0}, onion_o{0}, block_relay_o{0}, total_o{0}; // outbound conn counters
- size_t max_peer_id_length{2}, max_addr_length{0};
- bool is_asmap_on{false};
- std::vector<Peer> peers;
- const UniValue& getpeerinfo{batch[ID_PEERINFO]["result"]};
-
- for (const UniValue& peer : getpeerinfo.getValues()) {
- const std::string addr{peer["addr"].get_str()};
- const std::string addr_local{peer["addrlocal"].isNull() ? "" : peer["addrlocal"].get_str()};
- const int mapped_as{peer["mapped_as"].isNull() ? 0 : peer["mapped_as"].get_int()};
+ for (const UniValue& peer : batch[ID_PEERINFO]["result"].getValues()) {
+ const std::string network{peer["network"].get_str()};
+ const int8_t network_id{NetworkStringToId(network)};
+ if (network_id == UNKNOWN_NETWORK) continue;
+ const bool is_outbound{!peer["inbound"].get_bool()};
const bool is_block_relay{!peer["relaytxes"].get_bool()};
- const bool is_inbound{peer["inbound"].get_bool()};
- NetType net_type{NetType::ipv4};
- if (is_inbound) {
- if (IsAddrIPv6(addr)) {
- net_type = NetType::ipv6;
- ++ipv6_i;
- } else if (IsInboundOnion(addr_local, mapped_as)) {
- net_type = NetType::onion;
- ++onion_i;
- } else {
- ++ipv4_i;
- }
- if (is_block_relay) ++block_relay_i;
- } else {
- if (IsAddrIPv6(addr)) {
- net_type = NetType::ipv6;
- ++ipv6_o;
- } else if (IsOutboundOnion(addr, mapped_as)) {
- net_type = NetType::onion;
- ++onion_o;
- } else {
- ++ipv4_o;
- }
- if (is_block_relay) ++block_relay_o;
+ ++m_counts.at(is_outbound).at(network_id); // in/out by network
+ ++m_counts.at(is_outbound).at(m_networks_size); // in/out overall
+ ++m_counts.at(2).at(network_id); // total by network
+ ++m_counts.at(2).at(m_networks_size); // total overall
+ if (is_block_relay) {
+ ++m_counts.at(is_outbound).at(m_networks_size + 1); // in/out block-relay
+ ++m_counts.at(2).at(m_networks_size + 1); // total block-relay
}
if (DetailsRequested()) {
// Push data for this peer to the peers vector.
const int peer_id{peer["id"].get_int()};
+ const int mapped_as{peer["mapped_as"].isNull() ? 0 : peer["mapped_as"].get_int()};
const int version{peer["version"].get_int()};
- const std::string sub_version{peer["subver"].get_str()};
const int64_t conn_time{peer["conntime"].get_int64()};
const int64_t last_blck{peer["last_block"].get_int64()};
const int64_t last_recv{peer["lastrecv"].get_int64()};
@@ -435,10 +407,14 @@ public:
const int64_t last_trxn{peer["last_transaction"].get_int64()};
const double min_ping{peer["minping"].isNull() ? -1 : peer["minping"].get_real()};
const double ping{peer["pingtime"].isNull() ? -1 : peer["pingtime"].get_real()};
- peers.push_back({peer_id, mapped_as, version, conn_time, last_blck, last_recv, last_send, last_trxn, min_ping, ping, addr, sub_version, net_type, is_block_relay, !is_inbound});
- max_peer_id_length = std::max(ToString(peer_id).length(), max_peer_id_length);
- max_addr_length = std::max(addr.length() + 1, max_addr_length);
- is_asmap_on |= (mapped_as != 0);
+ const std::string addr{peer["addr"].get_str()};
+ const std::string age{conn_time == 0 ? "" : ToString((m_time_now - conn_time) / 60)};
+ const std::string sub_version{peer["subver"].get_str()};
+ m_peers.push_back({addr, sub_version, network, age, min_ping, ping, last_blck, last_recv, last_send, last_trxn, peer_id, mapped_as, version, is_block_relay, is_outbound});
+ m_max_addr_length = std::max(addr.length() + 1, m_max_addr_length);
+ m_max_age_length = std::max(age.length(), m_max_age_length);
+ m_max_id_length = std::max(ToString(peer_id).length(), m_max_id_length);
+ m_is_asmap_on |= (mapped_as != 0);
}
}
@@ -446,52 +422,56 @@ public:
std::string result{strprintf("%s %s%s - %i%s\n\n", PACKAGE_NAME, FormatFullVersion(), ChainToString(), networkinfo["protocolversion"].get_int(), networkinfo["subversion"].get_str())};
// Report detailed peer connections list sorted by direction and minimum ping time.
- if (DetailsRequested() && !peers.empty()) {
- std::sort(peers.begin(), peers.end());
- result += "Peer connections sorted by direction and min ping\n<-> relay net mping ping send recv txn blk uptime ";
- if (is_asmap_on) result += " asmap ";
- result += strprintf("%*s %-*s%s\n", max_peer_id_length, "id", IsAddressSelected() ? max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
- for (const Peer& peer : peers) {
+ if (DetailsRequested() && !m_peers.empty()) {
+ std::sort(m_peers.begin(), m_peers.end());
+ result += strprintf("Peer connections sorted by direction and min ping\n<-> relay net mping ping send recv txn blk %*s ", m_max_age_length, "age");
+ if (m_is_asmap_on) result += " asmap ";
+ result += strprintf("%*s %-*s%s\n", m_max_id_length, "id", IsAddressSelected() ? m_max_addr_length : 0, IsAddressSelected() ? "address" : "", IsVersionSelected() ? "version" : "");
+ for (const Peer& peer : m_peers) {
std::string version{ToString(peer.version) + peer.sub_version};
result += strprintf(
- "%3s %5s %5s%6s%7s%5s%5s%5s%5s%7s%*i %*s %-*s%s\n",
+ "%3s %5s %5s%7s%7s%5s%5s%5s%5s %*s%*i %*s %-*s%s\n",
peer.is_outbound ? "out" : "in",
peer.is_block_relay ? "block" : "full",
- NetTypeEnumToString(peer.net_type),
- peer.min_ping == -1 ? "" : ToString(round(1000 * peer.min_ping)),
- peer.ping == -1 ? "" : ToString(round(1000 * peer.ping)),
- peer.last_send == 0 ? "" : ToString(time_now - peer.last_send),
- peer.last_recv == 0 ? "" : ToString(time_now - peer.last_recv),
- peer.last_trxn == 0 ? "" : ToString((time_now - peer.last_trxn) / 60),
- peer.last_blck == 0 ? "" : ToString((time_now - peer.last_blck) / 60),
- peer.conn_time == 0 ? "" : ToString((time_now - peer.conn_time) / 60),
- is_asmap_on ? 7 : 0, // variable spacing
- is_asmap_on && peer.mapped_as != 0 ? ToString(peer.mapped_as) : "",
- max_peer_id_length, // variable spacing
+ peer.network,
+ PingTimeToString(peer.min_ping),
+ PingTimeToString(peer.ping),
+ peer.last_send == 0 ? "" : ToString(m_time_now - peer.last_send),
+ peer.last_recv == 0 ? "" : ToString(m_time_now - peer.last_recv),
+ peer.last_trxn == 0 ? "" : ToString((m_time_now - peer.last_trxn) / 60),
+ peer.last_blck == 0 ? "" : ToString((m_time_now - peer.last_blck) / 60),
+ m_max_age_length, // variable spacing
+ peer.age,
+ m_is_asmap_on ? 7 : 0, // variable spacing
+ m_is_asmap_on && peer.mapped_as != 0 ? ToString(peer.mapped_as) : "",
+ m_max_id_length, // variable spacing
peer.id,
- IsAddressSelected() ? max_addr_length : 0, // variable spacing
+ IsAddressSelected() ? m_max_addr_length : 0, // variable spacing
IsAddressSelected() ? peer.addr : "",
IsVersionSelected() && version != "0" ? version : "");
}
- result += " ms ms sec sec min min min\n\n";
+ result += strprintf(" ms ms sec sec min min %*s\n\n", m_max_age_length, "min");
}
// Report peer connection totals by type.
- total_i = ipv4_i + ipv6_i + onion_i;
- total_o = ipv4_o + ipv6_o + onion_o;
result += " ipv4 ipv6 onion total block-relay\n";
- result += strprintf("in %5i %5i %5i %5i %5i\n", ipv4_i, ipv6_i, onion_i, total_i, block_relay_i);
- result += strprintf("out %5i %5i %5i %5i %5i\n", ipv4_o, ipv6_o, onion_o, total_o, block_relay_o);
- result += strprintf("total %5i %5i %5i %5i %5i\n", ipv4_i + ipv4_o, ipv6_i + ipv6_o, onion_i + onion_o, total_i + total_o, block_relay_i + block_relay_o);
+ const std::array<std::string, 3> rows{{"in", "out", "total"}};
+ for (uint8_t i = 0; i < m_networks_size; ++i) {
+ result += strprintf("%-5s %5i %5i %5i %5i %5i\n", rows.at(i), m_counts.at(i).at(0), m_counts.at(i).at(1), m_counts.at(i).at(2), m_counts.at(i).at(m_networks_size), m_counts.at(i).at(m_networks_size + 1));
+ }
// Report local addresses, ports, and scores.
result += "\nLocal addresses";
- const UniValue& local_addrs{networkinfo["localaddresses"]};
+ const std::vector<UniValue>& local_addrs{networkinfo["localaddresses"].getValues()};
if (local_addrs.empty()) {
result += ": n/a\n";
} else {
- for (const UniValue& addr : local_addrs.getValues()) {
- result += strprintf("\n%-40i port %5i score %6i", addr["address"].get_str(), addr["port"].get_int(), addr["score"].get_int());
+ size_t max_addr_size{0};
+ for (const UniValue& addr : local_addrs) {
+ max_addr_size = std::max(addr["address"].get_str().length() + 1, max_addr_size);
+ }
+ for (const UniValue& addr : local_addrs) {
+ result += strprintf("\n%-*s port %6i score %6i", max_addr_size, addr["address"].get_str(), addr["port"].get_int(), addr["score"].get_int());
}
}
diff --git a/src/bitcoin-tx-res.rc b/src/bitcoin-tx-res.rc
index 3e49b820bc..b545ce9dbe 100644
--- a/src/bitcoin-tx-res.rc
+++ b/src/bitcoin-tx-res.rc
@@ -1,8 +1,8 @@
#include <windows.h> // needed for VERSIONINFO
#include "clientversion.h" // holds the needed client version information
-#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
-#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD
+#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD)
#define VER_FILEVERSION VER_PRODUCTVERSION
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index e22b3766cf..321d62fe4d 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -11,6 +11,7 @@
#include <consensus/consensus.h>
#include <core_io.h>
#include <key_io.h>
+#include <policy/policy.h>
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <script/script.h>
@@ -40,6 +41,7 @@ static void SetupBitcoinTxArgs(ArgsManager &argsman)
{
SetupHelpOptions(argsman);
+ argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-create", "Create new, empty TX.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-json", "Select JSON output", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -95,13 +97,16 @@ static int AppInitRawTx(int argc, char* argv[])
fCreateBlank = gArgs.GetBoolArg("-create", false);
- if (argc < 2 || HelpRequested(gArgs)) {
+ if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
// First part of help message is specific to this utility
- std::string strUsage = PACKAGE_NAME " bitcoin-tx utility version " + FormatFullVersion() + "\n\n" +
- "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n" +
- "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n" +
- "\n";
- strUsage += gArgs.GetHelpMessage();
+ std::string strUsage = PACKAGE_NAME " bitcoin-tx utility version " + FormatFullVersion() + "\n";
+ if (!gArgs.IsArgSet("-version")) {
+ strUsage += "\n"
+ "Usage: bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n"
+ "or: bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n"
+ "\n";
+ strUsage += gArgs.GetHelpMessage();
+ }
tfm::format(std::cout, "%s", strUsage);
@@ -192,8 +197,9 @@ static CAmount ExtractAndValidateValue(const std::string& strValue)
static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal)
{
int64_t newVersion;
- if (!ParseInt64(cmdVal, &newVersion) || newVersion < 1 || newVersion > CTransaction::MAX_STANDARD_VERSION)
+ if (!ParseInt64(cmdVal, &newVersion) || newVersion < 1 || newVersion > TX_MAX_STANDARD_VERSION) {
throw std::runtime_error("Invalid TX version requested: '" + cmdVal + "'");
+ }
tx.nVersion = (int) newVersion;
}
diff --git a/src/bitcoin-wallet-res.rc b/src/bitcoin-wallet-res.rc
index e9fa2dbb40..59346ab8f6 100644
--- a/src/bitcoin-wallet-res.rc
+++ b/src/bitcoin-wallet-res.rc
@@ -1,8 +1,8 @@
#include <windows.h> // needed for VERSIONINFO
#include "clientversion.h" // holds the needed client version information
-#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
-#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD
+#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD)
#define VER_FILEVERSION VER_PRODUCTVERSION
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp
index 8fdf1bae0f..68890fda2d 100644
--- a/src/bitcoin-wallet.cpp
+++ b/src/bitcoin-wallet.cpp
@@ -24,14 +24,16 @@ static void SetupWalletToolArgs(ArgsManager& argsman)
SetupHelpOptions(argsman);
SetupChainParamsBaseOptions(argsman);
+ argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-wallet=<wallet-name>", "Specify wallet name", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::OPTIONS);
argsman.AddArg("-debug=<category>", "Output debugging information (default: 0).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-descriptors", "Create descriptors wallet. Only for create", ArgsManager::ALLOW_BOOL, OptionsCategory::OPTIONS);
argsman.AddArg("-printtoconsole", "Send trace/debug info to console (default: 1 when no -debug is true, 0 otherwise).", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("info", "Get wallet info", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
argsman.AddArg("create", "Create new wallet file", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
- argsman.AddArg("salvage", "Attempt to recover private keys from a corrupt wallet", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
+ argsman.AddArg("salvage", "Attempt to recover private keys from a corrupt wallet. Warning: 'salvage' is experimental.", ArgsManager::ALLOW_ANY, OptionsCategory::COMMANDS);
}
static bool WalletAppInit(int argc, char* argv[])
@@ -42,16 +44,18 @@ static bool WalletAppInit(int argc, char* argv[])
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error_message);
return false;
}
- if (argc < 2 || HelpRequested(gArgs)) {
- std::string usage = strprintf("%s bitcoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" +
- "bitcoin-wallet is an offline tool for creating and interacting with " PACKAGE_NAME " wallet files.\n" +
- "By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n" +
- "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n" +
- "Usage:\n" +
- " bitcoin-wallet [options] <command>\n\n" +
- gArgs.GetHelpMessage();
-
- tfm::format(std::cout, "%s", usage);
+ if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
+ std::string strUsage = strprintf("%s bitcoin-wallet version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n";
+ if (!gArgs.IsArgSet("-version")) {
+ strUsage += "\n"
+ "bitcoin-wallet is an offline tool for creating and interacting with " PACKAGE_NAME " wallet files.\n"
+ "By default bitcoin-wallet will act on wallets in the default mainnet wallet directory in the datadir.\n"
+ "To change the target wallet, use the -datadir, -wallet and -testnet/-regtest arguments.\n\n"
+ "Usage:\n"
+ " bitcoin-wallet [options] <command>\n";
+ strUsage += "\n" + gArgs.GetHelpMessage();
+ }
+ tfm::format(std::cout, "%s", strUsage);
return false;
}
diff --git a/src/bitcoind-res.rc b/src/bitcoind-res.rc
index 3a64acd5d1..a98b50c899 100644
--- a/src/bitcoind-res.rc
+++ b/src/bitcoind-res.rc
@@ -1,8 +1,8 @@
#include <windows.h> // needed for VERSIONINFO
#include "clientversion.h" // holds the needed client version information
-#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
-#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD
+#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD)
#define VER_FILEVERSION VER_PRODUCTVERSION
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 455a82e390..b7bcb534ef 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -28,15 +28,6 @@
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
UrlDecodeFn* const URL_DECODE = urlDecode;
-static void WaitForShutdown(NodeContext& node)
-{
- while (!ShutdownRequested())
- {
- UninterruptibleSleep(std::chrono::milliseconds{200});
- }
- Interrupt(node);
-}
-
static bool AppInit(int argc, char* argv[])
{
NodeContext node;
@@ -57,11 +48,11 @@ static bool AppInit(int argc, char* argv[])
if (HelpRequested(args) || args.IsArgSet("-version")) {
std::string strUsage = PACKAGE_NAME " version " + FormatFullVersion() + "\n";
- if (args.IsArgSet("-version")) {
- strUsage += FormatParagraph(LicenseInfo()) + "\n";
- } else {
- strUsage += "\nUsage: bitcoind [options] Start " PACKAGE_NAME "\n";
- strUsage += "\n" + args.GetHelpMessage();
+ if (!args.IsArgSet("-version")) {
+ strUsage += FormatParagraph(LicenseInfo()) + "\n"
+ "\nUsage: bitcoind [options] Start " PACKAGE_NAME "\n"
+ "\n";
+ strUsage += args.GetHelpMessage();
}
tfm::format(std::cout, "%s", strUsage);
@@ -147,12 +138,10 @@ static bool AppInit(int argc, char* argv[])
PrintExceptionContinue(nullptr, "AppInit()");
}
- if (!fRet)
- {
- Interrupt(node);
- } else {
- WaitForShutdown(node);
+ if (fRet) {
+ WaitForShutdown();
}
+ Interrupt(node);
Shutdown(node);
return fRet;
diff --git a/src/bloom.h b/src/bloom.h
index 9307257852..24dc607cd9 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -94,7 +94,18 @@ public:
* insert()'ed ... but may also return true for items that were not inserted.
*
* It needs around 1.8 bytes per element per factor 0.1 of false positive rate.
- * (More accurately: 3/(log(256)*log(2)) * log(1/fpRate) * nElements bytes)
+ * For example, if we want 1000 elements, we'd need:
+ * - ~1800 bytes for a false positive rate of 0.1
+ * - ~3600 bytes for a false positive rate of 0.01
+ * - ~5400 bytes for a false positive rate of 0.001
+ *
+ * If we make these simplifying assumptions:
+ * - logFpRate / log(0.5) doesn't get rounded or clamped in the nHashFuncs calculation
+ * - nElements is even, so that nEntriesPerGeneration == nElements / 2
+ *
+ * Then we get a more accurate estimate for filter bytes:
+ *
+ * 3/(log(256)*log(2)) * log(1/fpRate) * nElements
*/
class CRollingBloomFilter
{
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index a34bf350fc..88cf5ef0a8 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -91,11 +91,8 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1199145601; // January 1, 2008
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1230767999; // December 31, 2008
- // The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000e1ab5ec9348e9f4b8eb8154");
-
- // By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x0000000000000000000f2adce67e49b0b6bdeb9de8b7c3d7e93b21e7fc1e819d"); // 623950
+ consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000001533efd8d716a517fe2c5008");
+ consensus.defaultAssumeValid = uint256S("0x0000000000000000000b9d2ec5a352ecba0592946514a92f14319dc2b367fc72"); // 654683
/**
* The message start string is designed to be unlikely to occur in normal data.
@@ -108,8 +105,8 @@ public:
pchMessageStart[3] = 0xd9;
nDefaultPort = 8333;
nPruneAfterHeight = 100000;
- m_assumed_blockchain_size = 320;
- m_assumed_chain_state_size = 4;
+ m_assumed_blockchain_size = 350;
+ m_assumed_chain_state_size = 6;
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
consensus.hashGenesisBlock = genesis.GetHash();
@@ -165,10 +162,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 0000000000000000000f2adce67e49b0b6bdeb9de8b7c3d7e93b21e7fc1e819d
- /* nTime */ 1585764811,
- /* nTxCount */ 517186863,
- /* dTxRate */ 3.305709665792344,
+ // Data from RPC: getchaintxstats 4096 0000000000000000000b9d2ec5a352ecba0592946514a92f14319dc2b367fc72
+ /* nTime */ 1603995752,
+ /* nTxCount */ 582083445,
+ /* dTxRate */ 3.508976121410527,
};
}
};
@@ -207,11 +204,8 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = 1199145601; // January 1, 2008
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = 1230767999; // December 31, 2008
- // The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000001495c1d5a01e2af8a23");
-
- // By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x000000000000056c49030c174179b52a928c870e6e8a822c75973b7970cfbd01"); // 1692000
+ consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000001db6ec4ac88cf2272c6");
+ consensus.defaultAssumeValid = uint256S("0x000000000000006433d1efec504c53ca332b64963c425395515b01977bd7b3b0"); // 1864000
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
@@ -257,10 +251,10 @@ public:
};
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 000000000000056c49030c174179b52a928c870e6e8a822c75973b7970cfbd01
- /* nTime */ 1585561140,
- /* nTxCount */ 13483,
- /* dTxRate */ 0.08523187013249722,
+ // Data from RPC: getchaintxstats 4096 000000000000006433d1efec504c53ca332b64963c425395515b01977bd7b3b0
+ /* nTime */ 1603359686,
+ /* nTxCount */ 58090238,
+ /* dTxRate */ 0.1232886622799463,
};
}
};
@@ -278,17 +272,17 @@ public:
bin = ParseHex("512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430210359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c452ae");
vSeeds.emplace_back("178.128.221.177");
vSeeds.emplace_back("2a01:7c8:d005:390::5");
- vSeeds.emplace_back("ntv3mtqw5wt63red.onion:38333");
+ vSeeds.emplace_back("v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333");
- consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000000d145533ce");
- consensus.defaultAssumeValid = uint256S("0x00000128807d9175c494e24d805fc7854f7d79aa965cbb128342ad8b70cecfa5"); // 5348
+ consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000019fd16269a");
+ consensus.defaultAssumeValid = uint256S("0x0000002a1de0f46379358c1fd09906f7ac59adf3712323ed90eb59e4c183c020"); // 9434
m_assumed_blockchain_size = 1;
m_assumed_chain_state_size = 0;
chainTxData = ChainTxData{
- // Data from RPC: getchaintxstats 4096 00000128807d9175c494e24d805fc7854f7d79aa965cbb128342ad8b70cecfa5
- /* nTime */ 1601382000,
- /* nTxCount */ 5435,
- /* dTxRate */ 0.001898346323372538,
+ // Data from RPC: getchaintxstats 4096 0000002a1de0f46379358c1fd09906f7ac59adf3712323ed90eb59e4c183c020
+ /* nTime */ 1603986000,
+ /* nTxCount */ 9582,
+ /* dTxRate */ 0.00159272030651341,
};
} else {
const auto signet_challenge = args.GetArgs("-signetchallenge");
@@ -297,6 +291,8 @@ public:
}
bin = ParseHex(signet_challenge[0]);
+ consensus.nMinimumChainWork = uint256{};
+ consensus.defaultAssumeValid = uint256{};
m_assumed_blockchain_size = 0;
m_assumed_chain_state_size = 0;
chainTxData = ChainTxData{
@@ -315,7 +311,9 @@ public:
consensus.signet_blocks = true;
consensus.signet_challenge.assign(bin.begin(), bin.end());
consensus.nSubsidyHalvingInterval = 210000;
+ consensus.BIP16Exception = uint256{};
consensus.BIP34Height = 1;
+ consensus.BIP34Hash = uint256{};
consensus.BIP65Height = 1;
consensus.BIP66Height = 1;
consensus.CSVHeight = 1;
@@ -324,13 +322,19 @@ public:
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false;
- consensus.nRuleChangeActivationThreshold = 1916;
- consensus.nMinerConfirmationWindow = 2016;
+ consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016
+ consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
+ consensus.MinBIP9WarningHeight = 0;
consensus.powLimit = uint256S("00000377ae000000000000000000000000000000000000000000000000000000");
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
+ // Activation of Taproot (BIPs 340-342)
+ consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].bit = 2;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
+
// message start is defined as the first 4 bytes of the sha256d of the block script
CHashWriter h(SER_DISK, 0);
h << consensus.signet_challenge;
@@ -394,11 +398,8 @@ public:
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nStartTime = Consensus::BIP9Deployment::ALWAYS_ACTIVE;
consensus.vDeployments[Consensus::DEPLOYMENT_TAPROOT].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT;
- // The best chain should have at least this much work.
- consensus.nMinimumChainWork = uint256S("0x00");
-
- // By default assume that the signatures in ancestors of this block are valid.
- consensus.defaultAssumeValid = uint256S("0x00");
+ consensus.nMinimumChainWork = uint256{};
+ consensus.defaultAssumeValid = uint256{};
pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf;
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
index 2aca18c188..3dfbae33bc 100644
--- a/src/chainparamsseeds.h
+++ b/src/chainparamsseeds.h
@@ -9,752 +9,1169 @@
*/
static SeedSpec6 pnSeed6_main[] = {
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x27,0xad,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x39,0x26,0x85}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x5c,0x27,0x27}, 15426},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0xe6,0x92,0xa3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x02,0x4a,0xaf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x08,0x12,0x1d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x27,0xde,0x27}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x03,0x0e,0xa8,0xc9}, 48333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x04,0x24,0x70,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x08,0x12,0x1f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x0e,0xc8,0xa7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x38,0x14,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x66,0x92,0x63}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x67,0x89,0x92}, 9333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x80,0x57,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x95,0xfa,0x4c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xb6,0x27,0xc8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x85,0x41,0x52}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbb,0x37,0xf2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbc,0x3e,0x18}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbc,0x3e,0x21}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbc,0xbb,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xbd,0x99,0xb3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc6,0x14,0xe3}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xc7,0x85,0xc1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0xfe,0x52,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0xed,0x93,0x0f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x08,0x26,0x59,0x98}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0d,0xe7,0x14,0xf9}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x12,0x1b,0x4f,0x11}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x14,0xb8,0x0f,0x74}, 8433},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x11,0xa0,0x9f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x1c,0xcd,0x61}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0x6a,0xfc,0xe6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xaf,0x00,0xca}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xaf,0x00,0xd4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xf1,0xfa,0xfc}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x17,0xf5,0x18,0x9a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x4c,0x7a,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x60,0x49,0x9c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x60,0x7d,0x39}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x9b,0xc4,0x1b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xcb,0x58,0xa7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xe9,0xf5,0xbc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xf6,0x1f,0xcd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x06,0x62,0x5e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x0e,0xc9,0x9c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x19,0xf1,0xe0}, 8335},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x2b,0x8c,0xbe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x56,0xb8,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x74,0xf6,0x09}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x8d,0x22,0xa6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x9b,0xc4,0xf6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0x9d,0x82,0xde}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xbc,0xb0,0xff}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x18,0xed,0x46,0x35}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1b,0x7c,0x04,0x43}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x11,0x46,0x50}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x15,0x08,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x2d,0x76,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x84,0x11,0x38}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x86,0x79,0xdf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0xad,0x30,0x3d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x22,0xcb,0xa9,0xac}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xb2,0x1f,0x04}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xb9,0xac,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xce,0xab,0x59}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xd0,0x57,0xcb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x3d,0xdb,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8f,0xd2,0x13}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8f,0xd3,0x53}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xeb,0x80,0x0b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xfc,0xbe,0x58}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x26,0x66,0x86,0x55}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x27,0x6d,0x00,0x96}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2a,0xc8,0x48,0xcd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xe5,0x84,0x66}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x20,0xd6,0xb7,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0x89,0xec,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xb9,0x91,0x69}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xd1,0x33,0xd4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x23,0xf5,0xaf,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x74,0x5f,0x29}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8f,0x09,0x6b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0x8f,0x74,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xbf,0xf4,0x95}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xd3,0x4e,0xfd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xdd,0xd1,0xde}, 24333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x25,0xe4,0x5c,0x6e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xe1,0x3e,0x6b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2b,0xe1,0x9d,0x98}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x24,0xb8,0x06}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x3a,0x31,0x23}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x4c,0x12,0x2f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x73,0xef,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x17,0x57,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x30,0xa8,0x10}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x55,0x55,0x08}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x55,0x55,0x09}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x81,0xb4,0xd6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x95,0x4e,0x80}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x97,0x7d,0xda}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x9a,0xff,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x9b,0x9d,0xef}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0x84,0x22}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x1c,0xcc,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x20,0x32,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x24,0x61,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x26,0xed,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x27,0x81,0x52}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa0,0xc3,0x79}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x3b,0x0d,0x23}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x80,0x28,0xad}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x80,0x8c,0xc1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0x92,0xf8,0x59}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xa6,0xa2,0x2d}, 20001},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x1e,0x76}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xbc,0x0f,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xa5,0x8e}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xe5,0xee,0xbb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xf9,0x53,0x52}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2e,0xfe,0xd9,0xa9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x34,0x72,0xc6}, 8885},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x58,0x54,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x6c,0x1d,0x98}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x6c,0x1e,0xa5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x4a,0xbf,0x22}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0x73,0x35,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xbb,0x1a,0x87}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xde,0x67,0xea}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x31,0xf5,0x32,0xe0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x35,0xfa,0xa2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0xe1,0xc6,0x43}, 6000},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2f,0xfd,0x05,0x63}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x31,0xe8,0x52,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x31,0xf7,0xd7,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x02,0x0d,0xa6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x22,0x27,0x48}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x2d,0xe8,0xbd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x32,0x44,0x68,0x5c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x44,0x24,0x39}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x33,0x9a,0x3c,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xf2,0x11,0x07}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x92,0xde,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x34,0xa9,0xee,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xc5,0x1e,0xdf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x36,0xe3,0x42,0x39}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0x9e,0x00,0x56}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3b,0x95,0xcd,0xc5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3c,0xfb,0x81,0x3d}, 8336},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3d,0x9b,0x05,0x04}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x2d,0x04,0x8b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x61,0xf4,0xf2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x6d,0x12,0x17}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x85,0xc2,0x9c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x8a,0x00,0xd9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xab,0x87,0xf2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3a,0xe5,0xd0,0x9e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3c,0xf4,0x6d,0x13}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x26,0x4b,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x4a,0x8f,0x0b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x50,0xe3,0x31}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0x98,0x3a,0x10}, 9421},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0x8f,0x22,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xd3,0x6f,0x7a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xe0,0xf9,0xf0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0xb6,0x77,0x24}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x40,0xe5,0x69,0x6f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x1b,0x68,0x70}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0xb7,0x4c,0x49}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x97,0xf2,0x9a}, 8335},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xce,0x0d,0x46}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xd2,0xa7,0xc7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xea,0xbc,0xa0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3e,0xfb,0x36,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x3f,0xe3,0x74,0xa2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x13,0x9b,0x52}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x41,0x5f,0x31,0x66}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x12,0xac,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xf0,0xed,0x9b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0xf0,0xed,0xac}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xcd,0x8c,0x91}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xd2,0xe4,0xcb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xdd,0xc1,0x37}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x43,0xde,0x83,0x97}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x6e,0x5a,0x6f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0x8e,0x21,0x24}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xc7,0x9d,0xb7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xca,0x80,0x13}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x44,0xce,0x15,0x90}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x1e,0xd7,0x2a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x37,0xea,0x4a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3b,0x12,0x16}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x91,0x7a,0xa0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xaf,0x31,0xe6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x40,0x30,0x29}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x21,0xe8,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x49,0x12,0x20}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x92,0x72,0x6f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x3b,0x12,0xce}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x40,0x21,0x47}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0x77,0xc1,0x09}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x45,0xd1,0x17,0x48}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0x7b,0x7d,0xed}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x46,0xb9,0x38,0x88}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x47,0x26,0x5a,0xeb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x0c,0x49,0x46}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0x35,0x86,0xb6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x7e,0x61,0x63}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x53,0x7e,0x96}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x54,0x80,0x9e}, 9333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x62,0xf2,0x61}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xe1,0x07,0x50}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xea,0xb6,0x27}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x48,0xfa,0xb8,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x49,0x53,0x67,0x4f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x76,0x89,0x77}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0x85,0x64,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xd7,0xdb,0xd6}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4a,0xdc,0xff,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x2d,0x33,0x29}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4b,0x9e,0x27,0xe7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x0b,0x11,0xbb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0x54,0x4f,0xd3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4c,0xa7,0xb3,0x4b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x35,0x9e,0x89}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x77,0xe5,0x6a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x35,0x35,0xc4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x46,0x10,0xf5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x69,0x57,0x61}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x78,0x71,0x45}, 8433},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x78,0x7a,0x16}, 8433},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0x78,0x7a,0x72}, 8433},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xa3,0x88,0x88}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xdc,0x8c,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xa6,0x53,0xa7}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4d,0xf7,0xb2,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x80,0x3e,0x34}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x80,0x4f,0x16}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x1b,0x8b,0x0d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x3f,0x1c,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x53,0x67,0x04}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x8d,0x7b,0x63}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x8f,0xd6,0xdf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4e,0x9f,0x63,0x55}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x4d,0x21,0x83}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x78,0x46,0x2f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x8e,0x81,0xda}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0xaf,0x7d,0xd2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x2f,0x9c,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x4d,0x85,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x65,0x01,0x19}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x75,0xc0,0xe5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x85,0xe4,0x37}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x4f,0x92,0x15,0xa3}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x59,0xcb,0xac}, 8001},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x5d,0xd5,0xf6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x6f,0x8e,0xd5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0x93,0x52,0xa5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd3,0xbf,0x0b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xd3,0xf5,0x97}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xc0,0x62,0x6e}, 8334},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xe5,0x1c,0x3c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xe5,0xa8,0x01}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xe8,0xf7,0xd2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xf2,0x27,0x4c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x50,0xfd,0x5e,0xfc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x04,0x66,0x45}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x00,0xc6,0x19}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x07,0x0d,0x54}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x0a,0xcd,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x75,0xe1,0xf5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xb1,0x9d,0x51}, 39993},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xeb,0xb9,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0x87,0x89,0xe1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xab,0x16,0x8f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xbf,0xe9,0x86}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xe8,0x4e,0x4b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x51,0xf2,0x5b,0x17}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x1d,0x3a,0x6d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x75,0xa6,0x4d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x76,0x14,0x25}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x92,0x32,0x8f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x92,0x99,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x88,0x63,0x16}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0x95,0x61,0x19}, 17567},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa9,0x82,0x3d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xb5,0xb3,0xe6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xb5,0xda,0xe5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xa5,0x13,0x30}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc2,0x99,0xe9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc3,0xed,0xfd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc5,0xda,0x61}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc5,0xd7,0x7d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc7,0x66,0x85}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xca,0xc5,0xe0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xd9,0xf5,0x07}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x6f,0x88}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x59,0x1b,0x32}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x59,0xfa,0x45}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xa7,0x1b,0x04}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd0,0xfe,0xb6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xc8,0xcd,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xca,0x44,0xe7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xdd,0x80,0x1f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x52,0xe4,0x06,0x83}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x55,0x8b,0x5e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x63,0xf5,0x14}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0x89,0x29,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xae,0xd1,0x57}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xd9,0x08,0x1f}, 44420},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xdd,0xd3,0x74}, 8335},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xf3,0x3b,0x29}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x53,0xfb,0xf1,0x00}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x26,0x03,0xf9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x28,0x5e,0xaa}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x26,0xb9,0x7a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0x5c,0x5c,0xf7}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xc0,0x10,0xea}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd1,0x09,0x17}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xea,0x60,0x73}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xf8,0x0e,0xd2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x77,0x53,0x19}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x90,0x77,0xde}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x91,0xee,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xc2,0x9e,0x7c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0x91,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd4,0xf4,0x5f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xd8,0x33,0x24}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x54,0xff,0xf9,0xa3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x19,0xff,0x93}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x46,0x9c,0xd1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0x91,0x8e,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xaa,0xe9,0x5f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xb8,0x8a,0x6c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xbe,0x00,0x05}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xca,0x0b,0x77}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xcc,0x60,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd0,0x45,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0x5a,0xa1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xf0,0xe9,0xdc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xbf,0xc8,0x33}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc0,0xbf,0x06}, 18500},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc2,0xee,0x83}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xc3,0x36,0x6e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xa1,0xfc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xd6,0xb9,0x33}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xf1,0x6a,0xcb}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x0f,0x26,0x3d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x4c,0x07,0x84}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x55,0xf6,0xa8,0xfc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x56,0x38,0xee,0xf7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x3d,0x5a,0xe6}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x4f,0x44,0x56}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x4f,0x5e,0xdd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x76,0x74,0xed}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0x78,0x08,0x05}, 20008},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xde,0x16,0xff}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xe9,0xb5,0x92}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xf6,0x2e,0x84}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xf9,0xcf,0x59}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x56,0x74,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x56,0x74,0x8e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x58,0x0d,0xf9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x57,0xf7,0x6f,0xde}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x54,0xde,0xfc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x56,0xf3,0xf1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x57,0x5d,0x34}, 1691},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x77,0xc5,0xc8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x81,0xfd,0x5e}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x93,0xf4,0xfa}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0x96,0xe6,0x5f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xca,0xca,0xdd}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd0,0x03,0xc3}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd4,0x2c,0x21}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x19,0x50,0x2a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x1c,0x75,0x1f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x58,0xd6,0x39,0x5f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x6a,0xc7,0x26}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x8e,0x4b,0x3c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x6c,0x7e,0xe4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x73,0x78,0x2b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0x85,0x44,0x41}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xbe,0x13,0xa2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd4,0x09,0x60}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xd4,0x4b,0x06}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xf8,0xfa,0x0c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x5e,0x53,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x59,0xf8,0xac,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x92,0x99,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0xb6,0xa5,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xb9,0xc6,0xea}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0x6a,0xbc,0xe5}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xc1,0xed,0x74}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xcc,0x63,0xb2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xcc,0x95,0x05}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd2,0x18,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd3,0x58,0x21}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd8,0x95,0x1c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xde,0x80,0x3b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x12,0xb4,0xe1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x35,0x59,0x7b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xf0,0x45,0xc3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xd6,0x46,0x3f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5b,0xe4,0x98,0xec}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0x0c,0x9a,0x73}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xf9,0x8f,0x2c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5c,0xff,0xb0,0x6d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x39,0x51,0xa2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x5a,0xc1,0xc3}, 8330},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x5a,0xcf,0x2e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x73,0x1a,0xba}, 20004},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x73,0xf0,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x0c,0x42,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x2e,0x36,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x73,0x14,0x82}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0x7b,0xb4,0xa4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xaf,0xcc,0x79}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xb4,0xb2,0xd5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xbd,0x91,0xa9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5d,0xf1,0xe4,0x66}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x13,0x07,0x37}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x13,0x80,0xcc}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x34,0x70,0xe3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x35,0x02,0xb5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x48,0x8f,0x1a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x67,0x78,0xad}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xed,0x40,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xed,0x50,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf2,0xff,0x1f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x18,0x30,0x54}, 15426},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x2a,0x02,0x71}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x9a,0x60,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x9c,0xae,0xc9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x9e,0xf6,0xb7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xb1,0xab,0x49}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xc7,0xb2,0xe9}, 8100},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xed,0x7d,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0xf7,0x86,0x4d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x30,0xe4,0x2d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x45,0xf9,0x3f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x4f,0x23,0x85}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x52,0x92,0x46}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x53,0x49,0x1f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x54,0xa4,0x2b}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x57,0xe2,0x38}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x5a,0x03,0xd2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x6e,0xea,0x5d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0x9c,0xfc,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd3,0xbd,0x03}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd9,0x09,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x09,0x50,0x6d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0xf5,0xda,0xf7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x68,0xce,0x03}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x1d,0xc3,0xcc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0xe7,0xc4,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x64,0xae,0x18}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa3,0x47,0x7e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xa4,0x41,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xae,0x42,0xd3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd3,0xae,0x89}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5f,0xd8,0x0b,0x9c}, 8433},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x60,0x2f,0x72,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x54,0xe8,0x69}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x61,0x63,0xcd,0xf1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x62,0x19,0xc1,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x73,0x19,0x0d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x20,0x13,0xb8}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x65,0x64,0xae,0xf0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x66,0x84,0xf5,0x10}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x0e,0xf4,0xbe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x25,0xcd,0x2f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x3c,0x6d,0xb8}, 20008},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x4c,0x30,0x05}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x54,0x54,0xfa}, 8335},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x55,0xbe,0xda}, 20000},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x63,0xa8,0x64}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x63,0xa8,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xd6,0x92,0x56}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x63,0xa8,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x6d,0x65,0xd8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x7a,0xf7,0x66}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0x81,0x0d,0x2d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xc6,0xc0,0x0e}, 20008},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xe0,0x77,0x63}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xe7,0xbf,0x07}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x67,0xeb,0xe6,0xc4}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xab,0xf2,0x9b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xc7,0xb8,0x0f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xf4,0xdf,0x97}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x69,0x1d,0x4c,0xc2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x2d,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0xb4,0x4d,0x15}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0x3a,0xfc,0x52}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x68,0xee,0xdc,0xc7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6a,0xa3,0x9e,0x7f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x96,0x29,0xb3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6b,0x9f,0x5d,0x67}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6c,0xb7,0x4d,0x0c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x48,0x53,0x7f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x09,0xaf,0x41}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x63,0x3f,0x9f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x6d,0x24,0x13}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x6e,0x51,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xad,0x70,0xe0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xca,0x6b,0x7d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xcd,0x6d,0x38}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xec,0x54,0x8d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xee,0x51,0x52}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x7b,0xd5,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0x86,0xe8,0x51}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xa9,0x14,0xa8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xc7,0xf1,0x94}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xe5,0xd2,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xec,0x69,0x28}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6d,0xf8,0xce,0x0d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x28,0x04,0x67}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x5a,0x8c,0xd9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x5a,0x9e,0xd4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x70,0xd5,0x67,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x2a,0x4a,0x41}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x6f,0x5a,0x8c,0xb3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x70,0xd7,0xcd,0xec}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x71,0x34,0x87,0x7d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x72,0x17,0xf6,0x89}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x2f,0x8d,0xfa}, 8885},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x73,0x46,0x6e,0x04}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x74,0x57,0x0f,0xf4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x74,0x22,0xbd,0x37}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0x67,0x7e,0x8c}, 28333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x76,0xbd,0xbb,0xdb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x03,0xd0,0xec}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x08,0x2f,0xe1}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0x11,0x97,0x3d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x77,0xab,0x86,0x57}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x12,0xee,0x27}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x4e,0xdf,0xba}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x62,0xcd,0x66}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0x19,0x18,0x1e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x78,0xf1,0x22,0x0a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x79,0x62,0xcd,0x64}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7a,0x70,0x94,0x99}, 8339},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7a,0x74,0x2a,0x8c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7c,0xa0,0x77,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7c,0xd9,0xeb,0xb4}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x7d,0xec,0xd7,0x85}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x0d,0xbd,0xd4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x81,0x61,0xf3,0x12}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x82,0xb9,0x4d,0x69}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0x72,0x0a,0xe9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbc,0x28,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x84,0xf9,0xef,0xa3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0x13,0xba,0xc3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x86,0xf9,0xbb,0x61}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x90,0xd7,0xdb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xbc,0x28,0xbf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x83,0xc1,0xdc,0x0f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x87,0x17,0x7c,0xef}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x21,0xb9,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x88,0x38,0xaa,0x60}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x89,0xe2,0x22,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8a,0xe5,0x1a,0x2a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8b,0x09,0xf9,0xea}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8d,0x65,0x08,0x24}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8f,0x59,0x79,0xcf}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x8f,0xb0,0xe0,0x68}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x02,0x45,0xe0}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x22,0xa1,0x41}, 18333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x93,0xfd,0x46,0xd0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x42,0x32,0x52}, 8335},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x5c,0x7f,0xd8}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x99,0x78,0x73,0x0f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x34,0x62,0x02}, 8444},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9b,0x04,0x74,0xa9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x5b,0x74,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x90,0x89,0x1d,0xb5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x42,0x32,0x32}, 8335},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0x48,0x96,0xe7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x94,0xaa,0xd4,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0xa7,0x63,0xbe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0x5c,0x10,0xbf}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9a,0xdd,0x1b,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9c,0x13,0x13,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9c,0x22,0xb2,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x0d,0x3d,0x42}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x0d,0x3d,0x43}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9c,0xf1,0x05,0xbe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x0d,0x3d,0x4c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0x0d,0x3d,0x50}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9d,0xe6,0xa6,0x62}, 14391},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0x4b,0xcb,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xb5,0x7d,0x96}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9e,0xb5,0xe2,0x21}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0x64,0xf2,0xfe}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0x64,0xf8,0xea}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0xfd,0x62,0xd1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x9f,0x8a,0x57,0x12}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa0,0x10,0x00,0x1e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa0,0x14,0x91,0x3e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x00,0xe3,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x00,0xe3,0x38}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x3e,0x12,0xe2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0x3e,0x1a,0xda}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x58,0xae}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xd1,0x01,0xe9}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf3,0xaf,0x56}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xf4,0x50,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xfa,0xbc,0x57}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa2,0xfa,0xbd,0x35}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa3,0x9e,0xca,0x70}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa3,0xac,0xb5,0xbf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0x3e,0x64,0x37}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa7,0x72,0x23,0x0c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa8,0x3e,0xa7,0xd1}, 8200},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa8,0xeb,0x4a,0x6e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa8,0xeb,0x5a,0xbc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xaa,0xf9,0x25,0xf3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x63,0x78,0x71}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x15,0xda,0x5f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x33,0xb1,0x02}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x5f,0x48,0xea}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa3,0x9e,0xf3,0xe6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa5,0x49,0x3e,0x1f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0x3e,0x52,0x67}, 32771},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa6,0x46,0x5e,0x6a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa7,0x56,0x5a,0xef}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xa9,0x2c,0x22,0xcb}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x5d,0x65,0x49}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xac,0x69,0x07,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x17,0x67,0x1e}, 8000},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x35,0x4f,0x06}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x46,0x0c,0x56}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0x59,0x1c,0x89}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xb0,0xb8,0x36}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd0,0x80,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xd1,0x2c,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xe7,0x39,0xc2}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xfe,0xcc,0x45}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xad,0xff,0xcc,0x7c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x41,0x87,0x3c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x5e,0x9b,0xe0}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x73,0x78,0xba}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x35,0xa0,0xaa}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x55,0xbc,0xd5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x72,0x66,0x29}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xae,0x72,0x7c,0x0c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x0a,0xe3,0x3b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x1f,0xe0,0xd6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x4a,0x88,0xed}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x63,0x02,0xcf}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x79,0x0e,0x9d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7a,0x9d,0xad}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x7e,0x55,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xc6,0x78,0xc5}, 8334},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x3d,0x8d,0xc6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x77,0xb7,0x22}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xea,0x1d,0xb8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0x6a,0xbf,0x02}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xa0,0xe4,0x09}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xbf,0xb6,0x03}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xd4,0xb9,0x99}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb0,0xf1,0x89,0xb7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb1,0x26,0xd7,0x49}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x10,0xde,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x84,0x02,0xf6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x8f,0xbf,0xab}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x94,0xac,0xd1}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x94,0xe2,0xb4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0x96,0x60,0x2e}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xb6,0xe3,0x32}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xec,0x89,0x3f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb2,0xff,0x2a,0x7e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb3,0x30,0xfb,0x29}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0x96,0x49,0x64}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0x2f,0xdc,0xf2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0xaa,0x8b,0x2f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb4,0x96,0x34,0x25}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0x27,0x20,0x63}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0x30,0x4d,0x1a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0x34,0xdf,0x34}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb5,0xee,0x33,0x98}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x58,0xdf,0xd0}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0x6e,0xdc,0xd2}, 30301},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb7,0xe6,0x5d,0x8b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5f,0x3a,0xa4}, 8663},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0x5f,0x3a,0xa6}, 8336},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0xa4,0x93,0x52}, 41333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x0f,0x5c,0x12}, 20993},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x3c,0xc7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x34,0x03,0xb9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x3d,0x8a,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb8,0xab,0xd0,0x6d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x27}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xb8}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x74,0x0f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x53,0x6e,0x35}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x53,0xd6,0x7b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x50,0xdb,0x84}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x55,0x03,0x8c}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x5f,0xdb,0x35}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x60,0x5e,0x18}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x66,0x47,0x06}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x8a,0x23,0xb7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x8c,0xfc,0xfd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x8f,0x91,0x71}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x6c,0xf4,0x29}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x86,0xe9,0x79}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x91,0x80,0x15}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x94,0x03,0xe3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x9d,0xa0,0xdc}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa3,0x2c,0x2c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb0,0xdd,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x99,0xc4,0xf0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x9e,0x72,0xb8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xa5,0xa8,0xc4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb5,0xe6,0x4a}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xb9,0x1a,0x8d}, 8111},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xba,0xd0,0xa2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xc6,0x3a,0x2f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xc6,0x3b,0xb7}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xd7,0xe0,0x16}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xe8,0x1c,0xfe}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xef,0xec,0x74}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xbd,0x84,0xb2}, 57780},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xd3,0x3b,0x32}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xe9,0x94,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xee,0x81,0x71}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xf9,0xc7,0x6a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0xfb,0xa1,0x36}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbb,0xbd,0x99,0x88}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x25,0x18,0xbe}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x2a,0x28,0xea}, 18333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x41,0xd4,0x8a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x41,0xd4,0x9d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x3d,0x2e,0x24}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x44,0x2d,0x8f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x7f,0xe5,0x69}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x83,0xb1,0x82}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x06,0x54}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x08,0x24}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x86,0x58,0x05}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x8a,0x11,0x5c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0x96,0x9d,0x0b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd0,0x6f,0x3e}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe7,0xb1,0x95}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x02,0x91,0xb1}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0x68,0xf9,0x2c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xd6,0x81,0x41}, 20012},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbc,0xe6,0xa8,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbd,0x22,0x0e,0x5d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbd,0xcf,0x2e,0x20}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbe,0xd3,0xcc,0x44}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xbf,0xd1,0x15,0xbc}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x03,0x0b,0x14}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x03,0x0b,0x18}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x22,0x38,0x3b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x03,0xb9,0xd2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x41,0xaa,0x0f}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x41,0xaa,0x32}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x92,0x89,0x12}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa6,0x2f,0x20}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xa9,0x5e,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0x9d,0xca,0xb2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xe3,0x50,0x53}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc0,0xfe,0x41,0x7e}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x0a,0xcb,0x17}, 8334},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x1d,0x39,0x04}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x19,0x06,0xce}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x2a,0x6e,0x1e}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x3a,0xc4,0xd4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x3b,0x29,0x0b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x54,0x74,0x16}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6c,0x83,0x2b}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x94,0x47,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xa9,0xf4,0xbe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0x6a,0x1c,0x08}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xbd,0xbe,0x7b}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xc2,0xa3,0x23}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc1,0xc2,0xa3,0x35}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x05,0x9f,0xc5}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x0e,0xf6,0xcd}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x87,0x5c,0x60}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x24,0x5b,0xfd}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x7e,0x71,0x87}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x87,0x87,0x45}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0x9e,0x5c,0x96}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc2,0xbb,0xfb,0xa3}, 31239},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x38,0x3f,0x04}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x38,0x3f,0x05}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x38,0x3f,0x0a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x43,0x8b,0x36}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x5f,0xe1,0x11}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x87,0xc2,0x08}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0x9a,0x71,0x5a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xce,0x14,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xca,0xa9,0x95}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xce,0x69,0x2a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xd1,0xf9,0xa4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc3,0xe0,0x74,0x14}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x01,0xe7,0x06}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xfb,0x53,0x13}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x30,0x53,0x3a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0x60,0x32,0xd3}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xbc,0xcc,0x19}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xc0,0x14,0xc9}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x4c,0xc2,0x07}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x57,0x74,0xd5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x1c,0xc2,0x52}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0xc8,0x2b,0xd7}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xb6,0xb8,0xcc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf7,0x07,0xd0}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc7,0xf7,0xf9,0xbc}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x07,0xfc,0x76}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x14,0xba,0xfe}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xc8,0x53,0xa6,0x88}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x37,0x57,0x2d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x4f,0xa7,0x41}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0x6c,0xd3,0x87}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0xa9,0x66,0x49}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x82,0x30,0x75}, 8885},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x84,0x5f,0x0a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x0e,0xf5,0xb4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x98,0xcb,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcd,0xd1,0xa2,0x62}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0xdd,0xb2,0x95}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcb,0x97,0xa6,0x7b}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x5d,0x71,0x6c}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcc,0x6f,0xf1,0xc3}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xce,0x7c,0x95,0x42}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0x73,0x66,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xcf,0xe5,0x2e,0x96}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x4c,0xfc,0xc6}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x64,0x0d,0x38}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x64,0xb2,0xaf}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd0,0x6e,0x63,0x69}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x06,0xd2,0xb3}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x85,0xdc,0x4a}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x97,0xed,0x47}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x95,0xaa,0x1f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x33,0x84,0xe2}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xf1,0x46,0xd5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x15,0x0f,0x16}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x88,0x53,0x08}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xe3,0x98,0x6c}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0xfe,0x17,0x74}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x6c,0xec,0xb4}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xc2,0xa5,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd1,0x8d,0x39,0x39}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd3,0x1b,0x93,0x43}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x22,0xe1,0x76}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x59,0xad,0xd8}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0x63,0xe2,0x24}, 9020},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd4,0xed,0x60,0x62}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd5,0x59,0x83,0x35}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x26,0x81,0xa4}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x86,0xa5,0x37}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0x92,0xfb,0x08}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xbd,0xbe,0x5f}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xe2,0x80,0xbd}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd8,0xec,0xa4,0x52}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x10,0xb9,0xa5}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x15,0x18,0x92}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x13,0xd8,0xd2}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x1a,0x20,0x0a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x40,0x2f,0x8a}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x40,0x85,0xdc}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0x5c,0x37,0xf6}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xd9,0xac,0xf4,0x09}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0x4b,0x8c,0x2d}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdb,0x4b,0x7a,0x2f}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0xe9,0x8a,0x82}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdd,0x82,0x1d,0xe6}, 18421},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0x7a,0x31,0x28}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xba,0xa9,0x01}, 8333},
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xde,0xde,0x2b,0x1d}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0x1f,0x71,0xf5}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xda,0xff,0xf2,0x72}, 8333},
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdc,0x85,0x27,0x3d}, 8333},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xdf,0x10,0x1e,0xaf}, 8333},
+ {{0x20,0x01,0x19,0xf0,0x60,0x01,0x30,0x6f,0x0e,0xc4,0x7a,0xff,0xfe,0x8f,0x66,0xec}, 8333},
{{0x20,0x01,0x1b,0xc0,0x00,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x01}, 8333},
{{0x20,0x01,0x1c,0x02,0x2f,0x18,0x0d,0x00,0xb6,0x2e,0x99,0xff,0xfe,0x49,0xd4,0x92}, 8333},
- {{0x20,0x01,0x02,0x50,0x02,0x00,0x00,0x07,0xd6,0xa9,0xfc,0xf4,0xe7,0x8d,0x2d,0x82}, 8333},
- {{0x20,0x01,0x41,0xc9,0x00,0x01,0x04,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x31}, 8333},
- {{0x20,0x01,0x41,0xd0,0x10,0x04,0x19,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
- {{0x20,0x01,0x44,0xb8,0x41,0x95,0x18,0x01,0x5c,0x73,0x5d,0x67,0xd2,0xa6,0x99,0x10}, 8333},
- {{0x20,0x01,0x04,0x70,0x88,0xff,0x00,0x2e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x20,0x01,0x41,0x00,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93}, 8333},
+ {{0x20,0x01,0x41,0x00,0x00,0x00,0x00,0x64,0xdc,0xaf,0xaf,0xff,0xfe,0x00,0x67,0x07}, 8333},
{{0x20,0x01,0x04,0x70,0x00,0x0a,0x0c,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x20,0x01,0x48,0x00,0x78,0x21,0x01,0x01,0xbe,0x76,0x4e,0xff,0xfe,0x04,0x9f,0x50}, 8333},
- {{0x20,0x01,0x48,0x01,0x78,0x19,0x00,0x74,0xb7,0x45,0xb9,0xd5,0xff,0x10,0xaa,0xec}, 8333},
- {{0x20,0x01,0x48,0xd0,0x00,0x01,0x21,0x63,0x00,0x00,0x00,0xff,0xfe,0xbe,0x5a,0x80}, 8333},
+ {{0x20,0x01,0x48,0x01,0x78,0x19,0x00,0x74,0xb7,0x45,0xb9,0xd5,0xff,0x10,0xa6,0x1a}, 8333},
{{0x20,0x01,0x4b,0xa0,0xff,0xfa,0x00,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93}, 8333},
+ {{0x20,0x01,0x06,0x10,0x19,0x08,0xff,0x01,0xf8,0x16,0x3e,0xff,0xfe,0x33,0x2e,0x32}, 8333},
{{0x20,0x01,0x06,0x38,0xa0,0x00,0x41,0x40,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x91}, 8333},
+ {{0x20,0x01,0x06,0x48,0x28,0x00,0x01,0x31,0x4b,0x1f,0xf6,0xfc,0x20,0xf7,0xf9,0x9f}, 8333},
{{0x20,0x01,0x06,0x78,0x07,0xdc,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x20,0x01,0x06,0x78,0x00,0xec,0x00,0x01,0x02,0x50,0x56,0xff,0xfe,0xa7,0x47,0xe9}, 8333},
- {{0x20,0x01,0x06,0x7c,0x10,0xec,0x2a,0x49,0x80,0x00,0x00,0x00,0x00,0x00,0x10,0x82}, 8333},
+ {{0x20,0x01,0x06,0x78,0x0c,0xc8,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x10,0x00,0x88}, 20008},
+ {{0x20,0x01,0x06,0x7c,0x12,0x20,0x08,0x0c,0x00,0x00,0x00,0x00,0x93,0xe5,0x0d,0xd2}, 8333},
+ {{0x20,0x01,0x06,0x7c,0x12,0x20,0x08,0x0c,0xe5,0xdc,0xad,0x0c,0x92,0x89,0xc2,0x8f}, 8333},
{{0x20,0x01,0x06,0x7c,0x16,0xdc,0x12,0x01,0x50,0x54,0x00,0xff,0xfe,0x17,0x4d,0xac}, 8333},
- {{0x20,0x01,0x06,0x7c,0x21,0xec,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a}, 8333},
+ {{0x20,0x01,0x06,0x7c,0x23,0x54,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22}, 8333},
{{0x20,0x01,0x06,0x7c,0x26,0xb4,0x00,0x12,0x7a,0xe3,0xb5,0xff,0xfe,0x04,0x6f,0x9c}, 8333},
- {{0x20,0x01,0x06,0x7c,0x2d,0xb8,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x45}, 8333},
- {{0x20,0x01,0x07,0x00,0x03,0x00,0x15,0x13,0x29,0xc7,0x24,0x30,0x19,0x0e,0xab,0x59}, 8333},
+ {{0x20,0x01,0x06,0x7c,0x02,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xfa}, 8333},
{{0x20,0x01,0x07,0x18,0x08,0x01,0x03,0x11,0x50,0x54,0x00,0xff,0xfe,0x19,0xc4,0x83}, 8333},
- {{0x20,0x01,0x08,0x18,0xe2,0x45,0xf8,0x00,0x04,0xdf,0x2b,0xdf,0xec,0xf5,0xeb,0x60}, 8333},
+ {{0x20,0x01,0x08,0xd8,0x08,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x99,0x03,0xc1}, 8333},
{{0x20,0x01,0x08,0xf1,0x14,0x04,0x37,0x00,0x8e,0x49,0x71,0x5a,0x2e,0x09,0xb6,0x34}, 9444},
- {{0x20,0x01,0x0b,0xa8,0x01,0xf1,0xf0,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x20,0x01,0x0b,0xb8,0x40,0x08,0x00,0x20,0x64,0x8c,0x5e,0xff,0xfe,0x74,0x0c,0xe4}, 8333},
- {{0x20,0x01,0x0d,0xa8,0xd8,0x00,0x08,0x21,0xa7,0xd5,0xf5,0xa7,0x53,0x0d,0xb7,0x1e}, 8333},
+ {{0x20,0x01,0x0b,0x07,0x5d,0x29,0x99,0xa5,0x19,0x4b,0x38,0x74,0xd6,0x5e,0xa9,0x0d}, 8333},
+ {{0x20,0x01,0x0b,0xa8,0x01,0xf1,0xf0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x20,0x01,0x0b,0xc8,0x12,0x00,0x00,0x00,0xda,0xc4,0x97,0xff,0xfe,0x2a,0x35,0x54}, 20008},
+ {{0x20,0x01,0x0d,0xa8,0x10,0x0d,0x00,0x22,0x10,0xfa,0xd8,0x5f,0x10,0xf2,0x21,0xfd}, 8333},
+ {{0x20,0x01,0x0d,0xa8,0x80,0x01,0x7a,0x39,0xf0,0x35,0x00,0x7d,0xb9,0x9f,0xeb,0x79}, 8333},
{{0x20,0x01,0x0e,0x42,0x01,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30}, 8333},
- {{0x20,0x01,0x0e,0x68,0x74,0x00,0x00,0x02,0x68,0x54,0x41,0x9e,0x22,0x1c,0x82,0xf3}, 8333},
- {{0x20,0x02,0xb6,0x10,0x1c,0xa3,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x10,0x1c,0xa3}, 8333},
- {{0x20,0x02,0xb6,0xff,0x3d,0xca,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0xff,0x3d,0xca}, 28364},
- {{0x24,0x00,0x26,0x51,0x42,0xe0,0x33,0x00,0x40,0xb4,0x57,0x6d,0xd1,0x4c,0x65,0xd4}, 8333},
+ {{0x24,0x00,0x24,0x12,0x01,0x03,0xc9,0x00,0x08,0x25,0x8f,0x20,0xea,0xff,0x65,0xc2}, 8333},
{{0x24,0x00,0x40,0x52,0x0e,0x20,0x4f,0x00,0x69,0xfe,0xbb,0x33,0x7b,0x1c,0xa1,0xca}, 8333},
- {{0x24,0x01,0x25,0x00,0x02,0x03,0x01,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15}, 8333},
+ {{0x24,0x01,0x18,0x00,0x78,0x00,0x01,0x05,0xbe,0x76,0x4e,0xff,0xfe,0x1c,0x0b,0x35}, 8333},
{{0x24,0x01,0x39,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x24,0x01,0xa4,0x00,0x32,0x00,0x56,0x00,0x14,0xee,0xf3,0x61,0x4b,0xdc,0x1f,0x7c}, 8333},
+ {{0x24,0x01,0xb1,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x01,0x50}, 8333},
{{0x24,0x01,0xd0,0x02,0x44,0x02,0x00,0x00,0x8f,0x28,0x59,0x1a,0x6e,0xa0,0xc6,0x83}, 8333},
- {{0x24,0x02,0xcb,0x40,0x10,0x00,0x05,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0xad}, 8333},
+ {{0x24,0x03,0x62,0x00,0x88,0x21,0x3d,0x68,0x19,0x5b,0x87,0xe9,0x68,0x19,0xd5,0xc8}, 8333},
+ {{0x24,0x05,0x65,0x80,0x21,0x40,0x3a,0x00,0xc2,0x8c,0x09,0x83,0x36,0x4b,0x5d,0x70}, 8333},
+ {{0x24,0x05,0x98,0x00,0xb9,0x11,0xa1,0x8a,0x58,0xeb,0xcd,0x3c,0x9d,0x82,0xea,0x4a}, 8333},
{{0x24,0x05,0xaa,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40}, 8333},
{{0x24,0x09,0x00,0x10,0xca,0x20,0x1d,0xf0,0x02,0x24,0xe8,0xff,0xfe,0x1f,0x60,0xd9}, 8333},
- {{0x24,0x09,0x8a,0x15,0x4a,0x1a,0x28,0x30,0x72,0x85,0xc2,0xff,0xfe,0x70,0x60,0xa4}, 8333},
- {{0x24,0x09,0x8a,0x1e,0x69,0x38,0xd2,0xc0,0x02,0xe0,0x70,0xff,0xfe,0x86,0xcb,0x59}, 8333},
- {{0x24,0x09,0x8a,0x28,0x04,0x21,0x25,0x80,0x02,0xe0,0x70,0xff,0xfe,0x8b,0x01,0x3e}, 8333},
- {{0x24,0x09,0x8a,0x28,0x04,0x21,0x27,0x70,0x02,0xe0,0x70,0xff,0xfe,0x87,0xfe,0xcb}, 8333},
+ {{0x24,0x09,0x8a,0x1e,0xa9,0xaf,0x36,0x60,0x1c,0x5a,0x5b,0x6b,0x8a,0x2d,0x98,0x48}, 8333},
+ {{0x24,0x09,0x8a,0x1e,0xa9,0xaf,0x36,0x60,0x04,0x04,0x39,0xba,0x88,0xf2,0xe8,0xdf}, 8333},
+ {{0x24,0x0b,0x00,0x10,0x91,0x41,0x04,0x00,0x49,0xb4,0x3a,0x2e,0x01,0xe5,0x08,0x4c}, 8333},
+ {{0x24,0x0d,0x00,0x1a,0x07,0x59,0x60,0x00,0xa7,0xb1,0x45,0x1a,0x88,0x74,0xe1,0xac}, 8333},
{{0x24,0x0d,0x00,0x1a,0x07,0x59,0x60,0x00,0xdd,0xab,0x31,0x41,0x4d,0xa0,0x88,0x78}, 8333},
- {{0x26,0x00,0x3c,0x01,0x00,0x00,0x00,0x00,0xf0,0x3c,0x91,0xff,0xfe,0xcd,0x1b,0x95}, 8333},
- {{0x26,0x00,0x6c,0x40,0x79,0x80,0x00,0x27,0x02,0x0a,0xf7,0xff,0xfe,0x69,0xf4,0xd5}, 8333},
- {{0x26,0x02,0xff,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc5,0xb8,0x44}, 8333},
- {{0x26,0x04,0x2d,0x80,0xc8,0x08,0x85,0x7b,0x08,0xd6,0x9e,0x1c,0x71,0x31,0x4b,0xea}, 8333},
+ {{0x26,0x00,0x88,0x05,0x24,0x00,0x01,0x4e,0x12,0xdd,0xb1,0xff,0xfe,0xf2,0x30,0x13}, 8333},
+ {{0x26,0x01,0x06,0x02,0x8d,0x80,0x0b,0x63,0xdc,0x3e,0x24,0xff,0xfe,0x92,0x05,0xeb}, 8333},
+ {{0x26,0x02,0xff,0xb6,0x00,0x04,0x27,0x98,0xf8,0x16,0x3e,0xff,0xfe,0x2f,0x54,0x41}, 8333},
+ {{0x26,0x02,0xff,0xb6,0x00,0x04,0x73,0x9e,0xf8,0x16,0x3e,0xff,0xfe,0x00,0xc2,0xb3}, 8333},
+ {{0x26,0x02,0xff,0xb8,0x00,0x00,0x00,0x00,0x02,0x08,0x00,0x72,0x00,0x57,0x02,0x00}, 8333},
+ {{0x26,0x04,0x13,0x80,0x41,0x11,0x93,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x26,0x04,0x43,0x00,0x00,0x0a,0x00,0x2e,0x02,0x1b,0x21,0xff,0xfe,0x11,0x03,0x92}, 8333},
+ {{0x26,0x04,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0x06}, 8112},
+ {{0x26,0x04,0x55,0x00,0x70,0x6a,0x40,0x00,0xfc,0x79,0xb9,0xbb,0x01,0xd7,0xc3,0x25}, 8333},
{{0x26,0x04,0x55,0x00,0xc1,0x34,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xfc}, 32797},
- {{0x26,0x04,0x55,0x00,0xc2,0xa3,0x7b,0x00,0x0c,0xc6,0x37,0x3b,0x44,0xa8,0xca,0xa4}, 8333},
- {{0x26,0x04,0x60,0x00,0x6e,0x85,0x4a,0x01,0xa8,0x2d,0xf9,0xff,0xfe,0xf5,0x28,0xb9}, 8333},
- {{0x26,0x04,0x77,0x80,0x03,0x03,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80}, 8333},
+ {{0x26,0x04,0x68,0x00,0x5e,0x11,0x01,0x62,0x5c,0x8f,0xd2,0xff,0xfe,0x26,0x14,0x6f}, 8333},
{{0x26,0x05,0x4d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50}, 8333},
- {{0x26,0x05,0x98,0x80,0x00,0x00,0x07,0x77,0x02,0x25,0x90,0xff,0xfe,0xfc,0x89,0x58}, 8333},
+ {{0x26,0x05,0x64,0x00,0x00,0x20,0x13,0xbf,0xdf,0x1d,0x18,0x1c,0x83,0xbb,0x22,0xe8}, 8333},
{{0x26,0x05,0xae,0x00,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03}, 8333},
{{0x26,0x05,0xc0,0x00,0x2a,0x0a,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02}, 8333},
- {{0x26,0x05,0xe0,0x00,0x11,0x27,0x08,0xfc,0xec,0x63,0xa1,0x91,0x32,0xc2,0x63,0x3c}, 8333},
- {{0x26,0x05,0xe2,0x00,0xd2,0x02,0x03,0x00,0x02,0x0c,0x29,0xff,0xfe,0xf1,0x85,0xec}, 8333},
- {{0x26,0x05,0xf7,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x31,0x5b,0x54}, 8333},
- {{0x26,0x06,0xc6,0x80,0x00,0x00,0x00,0x0b,0x38,0x30,0x34,0xff,0xfe,0x66,0x66,0x63}, 8333},
- {{0x26,0x07,0x44,0x80,0x00,0x02,0x00,0x01,0x00,0x38,0x01,0x02,0x00,0x69,0x00,0x70}, 8333},
- {{0x26,0x07,0x92,0x80,0x00,0x0b,0x07,0x3b,0x02,0x50,0x56,0xff,0xfe,0x21,0x9c,0x2f}, 8333},
- {{0x26,0x07,0xf1,0x28,0x00,0x40,0x17,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x26,0x07,0xf1,0x88,0x00,0x00,0x00,0x04,0xee,0xf4,0xbb,0xff,0xfe,0xcc,0x66,0x68}, 8333},
- {{0x26,0x07,0xf2,0xc0,0xe1,0xe2,0x00,0x11,0x10,0x44,0x9b,0x7a,0xb8,0x1e,0x1d,0x74}, 8333},
+ {{0x26,0x07,0xf2,0xc0,0xf0,0x0e,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54}, 8333},
+ {{0x26,0x07,0xf2,0xf8,0xad,0x40,0x0b,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x26,0x07,0xf4,0x70,0x00,0x08,0x10,0x48,0xae,0x1f,0x6b,0xff,0xfe,0x70,0x72,0x40}, 8333},
+ {{0x26,0x07,0xff,0x28,0x80,0x0f,0x00,0x97,0x02,0x25,0x90,0xff,0xfe,0x75,0x11,0x10}, 8333},
{{0x26,0x20,0x01,0x1c,0x50,0x01,0x11,0x18,0xd2,0x67,0xe5,0xff,0xfe,0xe9,0xe6,0x73}, 8333},
- {{0x26,0x20,0x00,0x6e,0xa0,0x00,0x00,0x01,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42}, 8333},
- {{0x28,0x04,0x01,0x4d,0xba,0xa7,0x96,0x74,0x02,0x1e,0x67,0xff,0xfe,0xa8,0xd7,0x99}, 8333},
- {{0x28,0x04,0x01,0x4d,0xba,0xa7,0x96,0x74,0x36,0x15,0x9e,0xff,0xfe,0x23,0xd6,0x10}, 8333},
- {{0x28,0x04,0x39,0xe8,0xff,0x85,0xa6,0x00,0x72,0x85,0xc2,0xff,0xfe,0xae,0x99,0x25}, 8333},
- {{0x28,0x04,0x0d,0x41,0xaa,0x01,0x16,0x00,0x5a,0x2d,0x3b,0x27,0x3b,0x83,0x2b,0x45}, 8333},
- {{0x2a,0x00,0x12,0xd8,0x70,0x01,0x00,0x01,0x46,0xe7,0x69,0x15,0x75,0xbe,0x92,0xf9}, 8333},
+ {{0x26,0x20,0x00,0x6e,0xa0,0x00,0x20,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06}, 8333},
+ {{0x28,0x04,0x01,0x4d,0x4c,0x93,0x98,0x09,0x97,0x69,0xda,0x80,0x18,0x32,0x34,0x80}, 8333},
+ {{0x2a,0x00,0x13,0x28,0xe1,0x01,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x63}, 8333},
{{0x2a,0x00,0x13,0x98,0x00,0x04,0x2a,0x03,0x02,0x15,0x5d,0xff,0xfe,0xd6,0x10,0x33}, 8333},
+ {{0x2a,0x00,0x13,0xa0,0x30,0x15,0x00,0x01,0x00,0x85,0x00,0x14,0x00,0x79,0x00,0x26}, 8333},
{{0x2a,0x00,0x16,0x30,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01}, 8333},
{{0x2a,0x00,0x17,0x68,0x20,0x01,0x00,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x6a}, 8333},
{{0x2a,0x00,0x18,0x28,0xa0,0x04,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x66}, 8333},
- {{0x2a,0x00,0x18,0x38,0x00,0x36,0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0xec,0x73}, 8333},
+ {{0x2a,0x00,0x18,0x38,0x00,0x36,0x00,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0xcb}, 8333},
{{0x2a,0x00,0x18,0x38,0x00,0x36,0x00,0x7d,0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0xc6}, 8333},
- {{0x2a,0x00,0x1f,0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x26}, 8333},
- {{0x2a,0x00,0x23,0xa8,0x41,0xd0,0x58,0x00,0x02,0x0c,0x29,0xff,0xfe,0x0d,0x6a,0x75}, 8333},
- {{0x2a,0x00,0x23,0xc5,0xfd,0x01,0x9f,0x00,0x63,0x17,0x7c,0x02,0x78,0x8f,0x88,0xea}, 8333},
- {{0x2a,0x00,0x60,0x20,0x13,0xc2,0x38,0x00,0xbe,0x6a,0xa1,0xc8,0xc9,0xe7,0x65,0xec}, 8333},
- {{0x2a,0x00,0x63,0xc2,0x00,0x08,0x00,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x00,0x71,0x43,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x27}, 8333},
- {{0x2a,0x00,0x7b,0x80,0x04,0x52,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x38}, 8333},
+ {{0x2a,0x00,0x1c,0x10,0x00,0x02,0x07,0x09,0x58,0xf7,0xe0,0xff,0xfe,0x24,0xa0,0xba}, 22220},
+ {{0x2a,0x00,0x1c,0x10,0x00,0x02,0x07,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17}, 22220},
+ {{0x2a,0x00,0x1f,0x40,0x50,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31}, 8333},
+ {{0x2a,0x00,0x60,0x20,0x13,0x95,0x14,0x00,0xba,0xf7,0x2d,0x43,0x60,0xb3,0x19,0x8b}, 8333},
+ {{0x2a,0x00,0x7c,0x80,0x00,0x00,0x01,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xaf}, 8333},
{{0x2a,0x00,0x8a,0x60,0xe0,0x12,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21}, 8333},
+ {{0x2a,0x00,0xab,0x00,0x06,0x03,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333},
+ {{0x2a,0x00,0xbb,0xe0,0x00,0xcc,0x00,0x00,0x62,0xa4,0x4c,0xff,0xfe,0x23,0x75,0x10}, 8333},
{{0x2a,0x00,0x0c,0xa8,0x0a,0x1f,0x30,0x25,0xf9,0x49,0xe4,0x42,0xc9,0x40,0x13,0xe8}, 8333},
- {{0x2a,0x00,0x0d,0x70,0x00,0x00,0x00,0x15,0xf8,0x16,0x3e,0xff,0xfe,0x73,0xd8,0x19}, 8333},
- {{0x2a,0x00,0xd8,0x80,0x00,0x05,0x03,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x39,0x78}, 8333},
- {{0x2a,0x01,0x02,0x38,0x42,0x0f,0x92,0x00,0xfa,0x5a,0x1a,0x4b,0x1e,0x6a,0xfa,0xdf}, 8333},
+ {{0x2a,0x00,0xd2,0xa0,0x00,0x0a,0x3d,0x00,0x1c,0xdf,0x38,0xbb,0xa7,0xd6,0xc2,0x51}, 8333},
+ {{0x2a,0x00,0xd8,0x80,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x0e}, 8333},
+ {{0x2a,0x00,0x0e,0xc0,0x72,0x07,0x91,0x00,0x5f,0x8f,0x25,0xdd,0x25,0x74,0x39,0x82}, 8333},
+ {{0x2a,0x00,0xf8,0x20,0x04,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36}, 8333},
+ {{0x2a,0x01,0x01,0x38,0xa0,0x17,0xb0,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42}, 8333},
{{0x2a,0x01,0x04,0x30,0x00,0x17,0x00,0x01,0x00,0x00,0x00,0x00,0xff,0xff,0x11,0x53}, 8333},
- {{0x2a,0x01,0x04,0x88,0x00,0x66,0x10,0x00,0x53,0xa9,0x15,0x73,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x01,0x04,0xf8,0x01,0x20,0x80,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8433},
- {{0x2a,0x01,0x05,0xf0,0xbe,0xef,0x00,0x05,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01}, 52101},
- {{0x2a,0x01,0x07,0x9c,0xce,0xbc,0xa6,0x30,0x9d,0xd8,0xef,0x55,0x83,0x74,0x92,0xa1}, 8333},
- {{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11}, 8333},
+ {{0x2a,0x01,0x04,0x90,0x00,0x16,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x01,0x4b,0x00,0x80,0x7c,0x1b,0x00,0xcd,0xa1,0x0c,0x6a,0x2b,0xad,0x24,0x18}, 8333},
+ {{0x2a,0x01,0x4b,0x00,0x80,0xe7,0x54,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x01,0x04,0xf8,0x01,0x92,0x42,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8433},
{{0x2a,0x01,0x07,0xa0,0x00,0x02,0x13,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03}, 8333},
- {{0x2a,0x01,0x07,0xc8,0xaa,0xb6,0x00,0xdb,0x50,0x54,0x00,0xff,0xfe,0xca,0xcf,0xc8}, 8333},
- {{0x2a,0x01,0x8b,0x81,0x64,0x03,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x01,0xcb,0x00,0x07,0xcd,0xb0,0x00,0xfa,0x1f,0x0b,0xd1,0x0f,0xe0,0x62,0xa6}, 8333},
- {{0x2a,0x01,0xcb,0x00,0x0d,0x3d,0x77,0x00,0x02,0x27,0x0e,0xff,0xfe,0x28,0xc5,0x65}, 8333},
+ {{0x2a,0x01,0x07,0xa7,0x00,0x02,0x14,0x67,0x0e,0xc4,0x7a,0xff,0xfe,0xe2,0x56,0x90}, 8333},
+ {{0x2a,0x01,0x07,0xc8,0xd0,0x02,0x01,0x0f,0x50,0x54,0x00,0xff,0xfe,0x5c,0xda,0xc7}, 8333},
+ {{0x2a,0x01,0x07,0xc8,0xd0,0x02,0x03,0x18,0x50,0x54,0x00,0xff,0xfe,0xbe,0xcb,0xb1}, 8333},
+ {{0x2a,0x01,0x87,0x40,0x00,0x01,0xff,0xc5,0x00,0x00,0x00,0x00,0x00,0x00,0x8c,0x6a}, 8333},
+ {{0x2a,0x01,0xcb,0x00,0x0f,0x98,0xca,0x00,0x50,0x54,0x00,0xff,0xfe,0xd4,0x76,0x3d}, 8333},
+ {{0x2a,0x01,0xcb,0x14,0x0c,0xf6,0xbc,0x00,0x21,0xe5,0xf1,0x2e,0x32,0xc8,0x01,0x45}, 8333},
+ {{0x2a,0x01,0x00,0xd0,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x45}, 8333},
{{0x2a,0x01,0x00,0xd0,0xbe,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12}, 8333},
- {{0x2a,0x01,0x00,0xd0,0xf3,0x4f,0x00,0x01,0x1f,0x67,0xe2,0x50,0x6a,0xeb,0xb9,0xc4}, 8333},
- {{0x2a,0x01,0x0e,0x34,0xee,0x6b,0x2a,0xb0,0x88,0xc2,0x1c,0x12,0xf4,0xeb,0xc2,0x6c}, 8333},
- {{0x2a,0x01,0x0e,0x35,0x2f,0xba,0x2e,0x90,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x01}, 8333},
- {{0x2a,0x02,0x12,0x05,0x50,0x5d,0xeb,0x50,0xbe,0xae,0xc5,0xff,0xfe,0x42,0xa9,0x73}, 8333},
- {{0x2a,0x02,0x12,0x0b,0x2c,0x3f,0x0a,0x90,0x10,0xdd,0x31,0xff,0xfe,0x42,0x50,0x79}, 8333},
- {{0x2a,0x02,0x01,0x30,0x03,0x00,0x15,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x02,0x13,0xb8,0x40,0x00,0x10,0x00,0x02,0x16,0xe6,0xff,0xfe,0x92,0x86,0x19}, 8333},
+ {{0x2a,0x01,0x0e,0x35,0x2e,0x40,0x68,0x30,0x02,0x11,0x32,0xff,0xfe,0xa6,0xde,0x3d}, 8333},
+ {{0x2a,0x02,0x12,0x05,0xc6,0xaa,0x60,0xc0,0x70,0xd8,0xaa,0xee,0xa8,0x2d,0x99,0x3c}, 8333},
+ {{0x2a,0x02,0x01,0x69,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x14}, 8333},
{{0x2a,0x02,0x01,0x80,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x5b,0x8f,0x53,0x8c}, 8333},
- {{0x2a,0x02,0x21,0x68,0x80,0x62,0xdb,0x00,0x96,0xde,0x80,0xff,0xfe,0xa3,0xfd,0x00}, 8333},
- {{0x2a,0x02,0x27,0x70,0x00,0x05,0x00,0x00,0x02,0x1a,0x4a,0xff,0xfe,0x44,0x83,0x70}, 8333},
- {{0x2a,0x02,0x27,0x88,0x08,0x64,0x0f,0xb3,0x5b,0x8a,0xc8,0xf7,0x9f,0xff,0xae,0x2d}, 8333},
- {{0x2a,0x02,0x2f,0x0d,0x06,0x07,0xbc,0x00,0x5e,0x9a,0xd8,0xff,0xfe,0x57,0x8b,0xc5}, 8333},
- {{0x2a,0x02,0x03,0x48,0x00,0x9a,0x83,0xb1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x03,0x48,0x00,0x62,0x5e,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2a,0x02,0x03,0x90,0x90,0x00,0x00,0x00,0x02,0x18,0x7d,0xff,0xfe,0x10,0xbe,0x33}, 8333},
- {{0x2a,0x02,0x47,0x80,0x00,0x08,0x00,0x06,0x00,0x02,0x35,0x4e,0x12,0x56,0x7a,0x04}, 8333},
- {{0x2a,0x02,0x05,0x78,0x4f,0x07,0x00,0x24,0x76,0xad,0xce,0xf7,0x93,0xc1,0xb9,0xb9}, 8333},
- {{0x2a,0x02,0x6d,0x40,0x30,0xf6,0xe9,0x01,0x89,0xb8,0xbb,0x58,0x02,0x5a,0x60,0x50}, 8333},
- {{0x2a,0x02,0x07,0x50,0x00,0x07,0x0c,0x11,0x50,0x54,0x00,0xff,0xfe,0x43,0xeb,0x81}, 8333},
{{0x2a,0x02,0x7a,0xa0,0x16,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xdc,0x8d,0xe0}, 8333},
- {{0x2a,0x02,0x7b,0x40,0x4f,0x62,0x19,0xae,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0x81,0x08,0x95,0xbf,0xea,0xe3,0x02,0x11,0x32,0xff,0xfe,0x8e,0xb5,0xb8}, 8333},
- {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x02,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x02,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a}, 8333},
- {{0x2a,0x03,0x1b,0x20,0x00,0x01,0xf4,0x10,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x3e}, 16463},
+ {{0x2a,0x02,0x7b,0x40,0xb0,0xdf,0x89,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x7b,0x40,0xb9,0x05,0x37,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x02,0x81,0x0d,0x8c,0xbf,0xf3,0xa8,0x96,0xc6,0x91,0xff,0xfe,0x17,0xae,0x1d}, 8333},
+ {{0x2a,0x02,0x83,0x89,0x01,0xc0,0x96,0x80,0x02,0x01,0x2e,0xff,0xfe,0x82,0xb3,0xcc}, 8333},
+ {{0x2a,0x02,0xa4,0x54,0xa5,0x16,0x00,0x01,0x05,0x17,0x09,0x28,0x7e,0x0d,0x95,0x7c}, 8333},
+ {{0x2a,0x02,0x0a,0xf8,0xfa,0xb0,0x08,0x04,0x01,0x51,0x02,0x36,0x00,0x34,0x01,0x61}, 8333},
+ {{0x2a,0x02,0x0a,0xf8,0xfa,0xb0,0x08,0x08,0x00,0x85,0x02,0x34,0x01,0x45,0x01,0x32}, 8333},
+ {{0x2a,0x02,0x0e,0x00,0xff,0xf0,0x01,0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a}, 8333},
+ {{0x2a,0x03,0x22,0x60,0x30,0x06,0x00,0x0d,0xd3,0x07,0x5d,0x1d,0x32,0xca,0x1f,0xe8}, 8333},
{{0x2a,0x03,0x60,0x00,0x08,0x70,0x00,0x00,0x00,0x46,0x00,0x23,0x00,0x87,0x02,0x18}, 8333},
{{0x2a,0x03,0x9d,0xa0,0x00,0xf6,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x03,0xc9,0x80,0x00,0xdb,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, 8333},
{{0x2a,0x03,0xe2,0xc0,0x01,0xce,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x04,0x21,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf2}, 8333},
- {{0x2a,0x04,0x21,0x80,0x00,0x01,0x00,0x0c,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x15}, 8333},
- {{0x2a,0x04,0x52,0xc0,0x01,0x01,0x09,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0xdc,0xbe}, 8333},
+ {{0x2a,0x04,0x35,0x44,0x10,0x00,0x15,0x10,0x70,0x6c,0xab,0xff,0xfe,0x6c,0x50,0x1c}, 8333},
+ {{0x2a,0x04,0x52,0xc0,0x01,0x01,0x03,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x2a,0x87}, 8333},
+ {{0x2a,0x04,0x52,0xc0,0x01,0x01,0x03,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x4c,0x27}, 8333},
{{0x2a,0x04,0xee,0x41,0x00,0x83,0x50,0xdf,0xd9,0x08,0xf7,0x1d,0x2a,0x86,0xb3,0x37}, 8333},
- {{0x2a,0x05,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00}, 8333},
- {{0x2a,0x05,0xfc,0x87,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
- {{0x2a,0x05,0xfc,0x87,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07}, 8333},
- {{0x2a,0x07,0x57,0x41,0x00,0x00,0x06,0x9d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x07,0x57,0x41,0x00,0x00,0x07,0xcd,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0x2a,0x07,0x72,0x00,0xff,0xff,0xc5,0x3f,0x00,0x00,0x00,0x00,0x00,0xe1,0x00,0x17}, 8333},
+ {{0x2a,0x05,0x6d,0x40,0xb9,0x4e,0xd1,0x00,0x02,0x25,0x90,0xff,0xfe,0x0d,0xcf,0xc2}, 8333},
+ {{0x2a,0x05,0xe5,0xc0,0x00,0x00,0x01,0x00,0x02,0x50,0x56,0xff,0xfe,0xb9,0xd6,0xcb}, 8333},
+ {{0x2a,0x05,0xfc,0x87,0x00,0x01,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}, 8333},
+ {{0x2a,0x05,0xfc,0x87,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08}, 8333},
+ {{0x2a,0x07,0x57,0x41,0x00,0x00,0x11,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
+ {{0x2a,0x07,0xa8,0x80,0x46,0x01,0x10,0x62,0xb4,0xb4,0xbd,0x2a,0x39,0xd4,0x7a,0xcf}, 51401},
+ {{0x2a,0x07,0xab,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x09,0x46}, 8333},
{{0x2a,0x07,0xb4,0x00,0x00,0x01,0x03,0x4c,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x02}, 8333},
+ {{0x2a,0x0a,0x8c,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb4}, 8333},
+ {{0x2a,0x0a,0xc8,0x01,0x00,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x83}, 8333},
{{0x2a,0x0b,0xae,0x40,0x00,0x03,0x4a,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15}, 8333},
- {{0x2a,0x0e,0xb7,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xd1,0xf0,0x5b}, 8333},
+ {{0x2a,0x0f,0xdf,0x00,0x00,0x00,0x02,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46}, 8333},
+ {{0x2c,0x0f,0xf5,0x98,0x00,0x05,0x00,0x01,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
{{0x2c,0x0f,0xfc,0xe8,0x00,0x00,0x04,0x00,0x0b,0x7c,0x00,0x00,0x00,0x00,0x00,0x01}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0x18,0xf0,0x4c,0x65,0x20,0x3d,0x5b,0x12,0x64}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0x01,0x01,0x59,0xad,0xa2,0x20,0x7d,0x6f,0x85}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd9,0xaf,0x04,0x04,0x09,0x8c,0xf1,0x2c,0x3f,0xae}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x80,0xc4,0x72,0x66,0xe6,0x0e,0x29,0xa7,0x02}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdd,0xbf,0xf3,0xc5,0x0b,0x37,0xa1,0xee,0x39,0xeb}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0xae,0x7d,0x48,0x29,0x92,0x51,0x85,0xf0,0xb4}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0x09,0xce,0x42,0x40,0x64,0x52,0xfc,0x59,0x34}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0xc0,0xf5,0xc6,0x6a,0x7c,0x53,0x03,0xb3,0x49}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe5,0x37,0x8d,0xe4,0xba,0x23,0x30,0xd9,0xfa,0x88}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xef,0xc7,0x89,0xa3,0x21,0x02,0x3e,0xee,0x2a,0x1f}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0xa8,0x02,0x51,0x62,0xfd,0xd9,0xc3,0x69,0x8c}, 8334},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0x27,0x51,0xf0,0x6a,0xf6,0x84,0x21,0xab,0x95}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0xd8,0x9c,0xf9,0x8c,0x42,0xb0,0x00,0x82,0xdd}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf1,0x29,0x11,0x5d,0xd0,0x90,0x39,0x07,0xa2,0x10}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf2,0x2b,0x55,0x12,0x44,0x72,0x64,0xc7,0x87,0x1c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0xd6,0x70,0x79,0xa9,0x98,0xa9,0x67,0x94,0x1b}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf6,0x18,0x60,0xd5,0xad,0xf0,0xfa,0xd2,0xb2,0xbc}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfe,0xb1,0xa6,0xf6,0x20,0x8e,0x38,0xcc,0x59,0x59}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf8,0x7f,0xda,0x07,0xa3,0x03,0xde,0x72,0x31,0x13}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfd,0xc1,0x07,0xc7,0xe4,0xbc,0x66,0xb6,0xa4,0x21}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x07,0xb8,0x70,0x22,0x12,0x5f,0xfc,0xbd,0x74,0xd5}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x00,0x7e,0x59,0x8c,0xb6,0xf4,0x0e,0x3b,0xee,0x24}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x28,0xf3,0x06,0x63,0x83,0xd9,0x62,0xbe,0x99}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x88,0x6e,0xfa,0x39,0x51,0xbf,0x19,0x63,0x06}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x90,0xd0,0xbb,0xf3,0x59,0x0d,0x26,0xca,0xed}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0x48,0xce,0x82,0x1c,0x14,0x75,0x95,0xfe,0x79}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x04,0xf7,0x6e,0xc1,0x12,0x16,0x4c,0x6a,0x21,0x24}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x05,0x1d,0xcc,0xa6,0x4f,0xe7,0x2b,0x81,0xd7,0xc2}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0b,0xac,0x6e,0x3e,0x25,0xf6,0xcc,0x8a,0x90,0x1c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x12,0x68,0x45,0x6b,0x4f,0xe5,0x6b,0xc3,0xe4,0x34}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x12,0x96,0x00,0x6a,0xe3,0x05,0xa2,0x1f,0xf4,0xa6}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x13,0xae,0x88,0xd3,0xfe,0x6b,0x4b,0x6d,0xd4,0x69}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x15,0xa1,0xa2,0xd0,0x5d,0xe3,0x16,0xfd,0xb9,0x22}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x19,0x80,0xd8,0xfc,0x65,0x2c,0x80,0x20,0x61,0x8b}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1a,0x43,0x29,0x3d,0x95,0x58,0xbc,0x84,0xa1,0x12}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1b,0x0b,0x67,0x57,0xb8,0x13,0x5f,0x5a,0x2d,0x09}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1b,0xf4,0x45,0x14,0x37,0xa0,0x5e,0x32,0xc6,0x7c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0xb5,0x42,0x87,0x01,0x89,0xa7,0x99,0x4a,0x72}, 4333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x20,0xd4,0xc2,0x90,0x00,0x7d,0x41,0x53,0xcd,0x54}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x22,0x46,0xe2,0x63,0x74,0x06,0x36,0x2c,0xfc,0x32}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x22,0xc0,0x35,0xd6,0xc5,0x58,0x00,0x7b,0xb9,0x91}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x29,0x4f,0x7f,0x4e,0x70,0xf9,0x12,0x17,0x0e,0x80}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x5a,0xdc,0xcc,0x8e,0x6f,0xfb,0x46,0xfb,0xb8}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xb1,0x73,0xba,0xcd,0xb8,0xeb,0xfc,0x60,0x36}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xca,0x2b,0xad,0x7a,0x9c,0x25,0xa5,0xf1,0x22}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xd6,0x3d,0x06,0xf8,0xae,0x71,0xce,0x8e,0x5c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3a,0xda,0xd3,0xb7,0x57,0x4e,0xa0,0x52,0xc1,0x32}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3b,0x61,0x66,0x41,0x0a,0x2b,0x1a,0xa7,0x8d,0x20}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3d,0x58,0x97,0x54,0x60,0x93,0x90,0xde,0x6e,0xcd}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3d,0xb2,0x20,0xb4,0x8d,0x7f,0x87,0x27,0xf9,0xd6}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x47,0x48,0xb5,0xdb,0x2d,0x1a,0x68,0xa2,0x6b,0x9a}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x40,0x1f,0x57,0xdb,0x32,0xe1,0x9e,0x15,0xf8,0xaa}, 8885},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0x7e,0x59,0x54,0xd8,0x85,0x9d,0x6b,0xa8,0x4d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x42,0xe8,0xac,0xa4,0x19,0xba,0xef,0x10,0xd2,0xd8}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x54,0xac,0x5c,0x52,0x2d,0x32,0xd9,0xee,0xd3,0xe1}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x58,0xe9,0xa3,0x85,0x0e,0x8a,0xaa,0x3c,0x31,0x20}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5d,0x6a,0x62,0x0d,0xef,0x63,0xd0,0x6a,0x0c,0xf9}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x62,0xb6,0x16,0x91,0xfd,0xa0,0x5d,0x4f,0xa3,0x9c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0x0e,0xfe,0x6b,0x13,0x0d,0x91,0xe8,0x17,0xda}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0x54,0x79,0x04,0x7e,0xb1,0xed,0xf7,0x39,0x0f}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0xd8,0x18,0xa4,0x55,0xa6,0xa5,0xe4,0x89,0xcc}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x69,0x78,0x8c,0x3d,0xb8,0x4d,0x8a,0xf1,0x25,0x9f}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x87,0x6f,0x62,0xd9,0x9e,0xc7,0x0b,0x5e,0x85}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0x24,0xbe,0xb4,0x1e,0x49,0x20,0x64,0x6d,0x7e}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x73,0xc8,0xd1,0x50,0x24,0x0c,0x21,0x7d,0x86,0x89}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x75,0x42,0xaa,0x98,0x6b,0x5a,0xb7,0x7b,0x90,0x07}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0xb4,0x92,0x1f,0xda,0x2a,0xa1,0xb0,0xe1,0xf2}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7a,0x84,0x6b,0x97,0x5b,0xb4,0xb6,0xbb,0x42,0xb0}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x80,0xe6,0x0a,0x7f,0x48,0x2d,0x81,0x47,0x4f,0xc1}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x06,0xd8,0xc3,0x1a,0x76,0x73,0xb6,0xe6,0x10}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x89,0x00,0x3c,0x05,0x13,0xed,0x49,0x81,0x1c,0x9e}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x96,0x88,0xfb,0x80,0x5f,0x75,0x71,0xbf,0x46,0x89}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x90,0x26,0xe2,0xde,0x42,0xdd,0xd2,0x01,0xde,0x4c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x95,0x7a,0xe4,0x4c,0xad,0x93,0x0a,0xe1,0x6e,0xd4}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa1,0x66,0x1b,0x73,0x28,0xed,0x97,0x91,0x58,0xee}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa6,0x76,0xfa,0x8c,0xe8,0x26,0xf7,0xfd,0x56,0xf6}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xae,0xaf,0xf3,0x3d,0x3b,0x91,0xee,0x56,0xaf,0x5d}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0xab,0xcf,0x1e,0x73,0xf1,0xb0,0x8b,0x8d,0x81}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0xb6,0x1d,0xc2,0xe2,0xb0,0xa3,0x10,0x43,0x4e}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0x88,0x41,0x25,0x9c,0xb7,0x14,0xef,0x78,0xbf}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb3,0x2e,0x2f,0x02,0x4a,0xe0,0x3b,0x7c,0x02,0xe7}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb4,0x22,0x02,0xb7,0x99,0x02,0xf6,0x10,0x84,0xf1}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb9,0xd1,0xdb,0xf6,0x02,0xe7,0x08,0xbc,0x0d,0x5c}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xba,0xbc,0x14,0xad,0x86,0xad,0x9c,0x9a,0xbb,0x29}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbb,0x0d,0x1f,0x96,0x4c,0x7f,0xc2,0x60,0xd2,0x2a}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbb,0x85,0x5c,0xec,0x79,0xc5,0x34,0xac,0xd3,0xc5}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbd,0x7e,0xf9,0xf8,0x93,0xb5,0xd1,0x83,0x4a,0x5e}, 8444},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc5,0x19,0x7f,0x82,0x49,0xf9,0x48,0xe7,0x65,0x02}, 8333},
- {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcb,0x00,0x31,0xca,0x04,0x5d,0xb4,0xec,0x58,0xa1}, 8444}
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xbc,0x4a,0x3c,0x6d,0x03,0xa9,0x4e,0x1f,0x55}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0x8f,0xf0,0xf8,0xbb,0x10,0x00,0x18,0x42,0x54}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xec,0x32,0xc1,0x59,0x9c,0xd8,0x46,0xd5,0x48}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd6,0xf0,0x8d,0x96,0x37,0xc3,0x27,0x61,0x9a,0x24}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd0,0x12,0xe6,0xed,0x8e,0xc1,0x78,0x8d,0x1c,0x21}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd0,0x4a,0xc5,0xbd,0x5d,0xe9,0xca,0x57,0xaf,0xc4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd0,0x94,0xc0,0x97,0xd2,0x32,0xed,0x81,0x92,0x67}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd1,0xd5,0x49,0x23,0xa6,0x10,0x01,0x49,0xda,0x05}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd2,0x2a,0x76,0x2c,0x37,0x09,0x9a,0xa1,0x61,0x4b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd3,0x19,0x77,0x50,0xf5,0xf3,0x48,0x17,0x59,0x50}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd4,0x24,0xda,0xf8,0x97,0x6d,0x28,0x80,0x47,0xf9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd4,0x28,0x30,0x9d,0x6d,0xac,0x1e,0xb4,0x6e,0x59}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd5,0x13,0x71,0x95,0xd5,0x2e,0x12,0xf6,0x0e,0x6e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd5,0xc6,0x62,0x50,0xb1,0x22,0xb6,0x4a,0x31,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd5,0xc7,0x99,0x46,0x87,0x91,0x13,0xc9,0xc9,0x16}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0x22,0x06,0xea,0xce,0x87,0x08,0x09,0x32,0x52}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0xa1,0xf5,0x1c,0xe4,0x4e,0x97,0x71,0xee,0xc5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0xf7,0x64,0x8e,0x4f,0xa3,0xbb,0xaa,0x4f,0x30}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0xfc,0xa5,0x92,0x7d,0xbc,0x03,0x13,0x69,0x35}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdf,0xd5,0x61,0xfc,0xb7,0x73,0xff,0xef,0x2f,0xaa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd9,0x3b,0x3f,0x9e,0x1c,0x02,0xe7,0xd9,0xba,0xb7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd9,0x83,0x73,0x90,0x25,0x3b,0xa9,0x4b,0x18,0x5b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xd9,0xcc,0x14,0xe4,0x9a,0x68,0x6d,0x8a,0x12,0xc5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xda,0x29,0x4a,0xc4,0x7a,0xb0,0x0e,0x0d,0x0a,0xee}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xda,0x67,0x7a,0x24,0x60,0x45,0x8f,0xe4,0x2e,0x74}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xda,0xfa,0x48,0x68,0x74,0xfb,0x2b,0x21,0x27,0x80}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdb,0x5c,0x56,0x99,0xb0,0x5c,0x08,0x43,0xb7,0xee}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdc,0x79,0xc1,0x8f,0x29,0x44,0xf2,0xdc,0x00,0xf6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xdd,0x66,0x1a,0x59,0x93,0x73,0x7f,0x58,0x76,0x19}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0x9c,0x7c,0xce,0x79,0xe3,0xc8,0xa4,0x73,0x66}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0xca,0xbd,0xa2,0xab,0xe5,0x7b,0xe4,0xca,0x71}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0xd1,0xe8,0x45,0x7a,0x42,0x60,0x2b,0x2c,0xde}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe7,0xe9,0x47,0x9b,0x22,0x6c,0x6c,0x03,0xba,0x6e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe0,0xba,0x25,0x23,0x7f,0x25,0x5c,0x51,0xcb,0xc3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0x21,0xbf,0x26,0x37,0xfd,0xe9,0x89,0x95,0xe2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0x2c,0xa1,0xde,0xa2,0x37,0x7e,0x01,0xc5,0xa8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe1,0x57,0x53,0x20,0x2d,0x66,0x9a,0xb1,0xed,0xa0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe2,0x00,0xe6,0xcf,0x0c,0xe7,0xd0,0xc0,0x58,0x9c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe2,0x6f,0x9d,0xfd,0xce,0xa7,0x40,0x6f,0xfb,0x62}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0x1a,0xaa,0xa7,0xc7,0x07,0xf6,0x48,0x34,0x2a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0x5b,0x4c,0x5d,0x9d,0x57,0x66,0xbc,0x26,0x1b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0x73,0xac,0x1b,0x82,0x6b,0xa6,0x4d,0x91,0x3f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe3,0xdd,0x9b,0x1f,0xdd,0xf7,0x30,0x6c,0x8c,0x6a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe4,0x0c,0x50,0xf7,0xd1,0xab,0xc2,0xc2,0x4a,0xff}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe4,0x64,0x0b,0xeb,0x73,0x04,0x33,0x66,0x21,0x89}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe5,0x3a,0x9e,0x83,0x1e,0x88,0x24,0xeb,0x4f,0x8c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe5,0x5d,0x1a,0xcd,0xd8,0x21,0x8f,0xcc,0x86,0xb1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0xa5,0xc4,0xf5,0xeb,0x1d,0x96,0xfc,0x9e,0x76}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe8,0x02,0xf4,0x22,0x05,0xa9,0x14,0xe2,0x26,0x2e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe8,0x30,0x3c,0xde,0xfe,0x4e,0x1d,0x9d,0xb4,0x99}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe8,0xaf,0x91,0xca,0x33,0x72,0xba,0x33,0x3b,0x80}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x07,0x44,0x29,0xf4,0x1a,0x09,0xb4,0xe2,0x25}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x1e,0x40,0x15,0x4c,0xc0,0x38,0x5a,0xf4,0x7d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0x71,0x75,0xe6,0x68,0x16,0xe7,0xe6,0xba,0x79}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xe9,0xc7,0xe2,0x60,0x96,0xee,0x02,0xd8,0x78,0xc1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xea,0x70,0x5c,0x9e,0xca,0x90,0x7d,0x48,0xc5,0xfa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0x5c,0xe8,0x18,0x53,0xef,0xbe,0x83,0x77,0xf5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0x64,0x56,0x71,0xb0,0x86,0x72,0xf8,0xa6,0x2f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0xa1,0x29,0xde,0x4f,0xc9,0xd6,0x64,0x90,0xbe}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xeb,0xf3,0x96,0x0f,0x93,0x2b,0x9b,0x18,0x64,0x3a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xec,0x84,0xa6,0x5f,0x98,0xa0,0x82,0xd7,0xf1,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xed,0x09,0xfb,0x3a,0x39,0x0b,0x7c,0x77,0x37,0x64}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xed,0xae,0x7b,0xea,0x6e,0xcb,0xdd,0x52,0xfb,0x3b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xed,0xd5,0xbc,0x51,0xbb,0xf1,0x37,0xa2,0x6f,0x88}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xee,0x4c,0x79,0xe8,0xdf,0xa8,0xa4,0x07,0xa3,0xdd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf6,0x86,0x21,0xbe,0xa3,0x72,0xcb,0x95,0x0f,0x2b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf6,0xc2,0xa7,0x69,0x87,0x45,0xda,0xdd,0x07,0xe3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf7,0xce,0x9a,0x96,0xbe,0xb2,0x05,0x30,0x2d,0x9d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf1,0xbc,0xa7,0x71,0x4b,0x51,0x7a,0x09,0xac,0x68}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf2,0xbb,0x98,0x90,0x97,0xb7,0x04,0x01,0xdd,0x1d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf2,0x8b,0xd0,0x60,0xeb,0x79,0x1b,0x8b,0x18,0x12}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf3,0x00,0x83,0x5d,0x35,0x11,0x27,0xc7,0xa2,0x64}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0x49,0x29,0x57,0x83,0xab,0xd6,0x1e,0xa0,0xe7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0x52,0x4b,0xf8,0xd8,0xa0,0x28,0x8d,0x8b,0xa4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0x94,0x66,0x97,0x9b,0x7b,0xce,0x3a,0xa6,0x80}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf4,0xa7,0x70,0x38,0x74,0xb2,0x24,0x6e,0xca,0x07}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf5,0xe1,0x8e,0x4e,0x5e,0x0b,0xbd,0x4e,0x8c,0xcc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf8,0x2a,0xd5,0xec,0x70,0x79,0xa9,0xad,0xa6,0xa0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf9,0x4b,0xcb,0x2b,0x5e,0xf3,0x5d,0xad,0xce,0xed}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xf9,0xd0,0xf0,0xd3,0x25,0x18,0xb1,0x98,0x29,0x46}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfc,0x92,0xc5,0xe6,0x33,0x3a,0x56,0xf2,0xe0,0x6a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfc,0xe9,0x3d,0xe6,0x7a,0x02,0xad,0x16,0x5b,0xd7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfd,0x0f,0x24,0xe5,0x3e,0x6d,0xf6,0x32,0xb6,0xf3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfd,0x99,0xcb,0x49,0xdb,0xb5,0x41,0x3b,0xb4,0x33}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xfe,0x14,0xcc,0xd3,0x01,0xb0,0xf4,0xf9,0xe4,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x06,0xbe,0x1a,0x9d,0x0d,0x07,0x31,0xad,0xa6,0xee}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x07,0x77,0x59,0x8d,0x9f,0xa2,0x09,0x3e,0xd4,0x6b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x07,0x7d,0xdf,0xea,0xe9,0xa3,0x8a,0xd9,0xe8,0x6f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x00,0x5f,0xae,0xa9,0xa8,0x28,0xe4,0xd1,0x6a,0x35}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x01,0x0b,0x7f,0xd0,0x39,0x78,0x17,0xf1,0x2c,0x0a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x3b,0x1d,0x0d,0x0e,0xcb,0x89,0xf8,0xc4,0x79}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0x1f,0x47,0xbc,0xe8,0x9e,0xc8,0xd3,0x19,0xe9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xcc,0xf4,0xa7,0x06,0x1e,0xcd,0x36,0xb1,0xef}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x02,0xd0,0x7a,0x03,0xf1,0x3e,0x05,0xce,0xe8,0xf1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0x36,0x6c,0x60,0xb8,0x6d,0xf3,0x6c,0x5c,0xf7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x03,0x54,0xec,0xe4,0xa7,0x5e,0xa3,0xba,0x0b,0xd4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x04,0xf7,0x3b,0x25,0x61,0x98,0xb4,0xb8,0x36,0x1d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x05,0x60,0xe0,0xaf,0xfa,0x7b,0x05,0xee,0x0f,0x08}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x05,0x98,0x3c,0xe8,0xb2,0xd8,0x7a,0x7e,0xd2,0x7d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x06,0x31,0x67,0xa3,0x1f,0xf8,0x69,0x31,0xa6,0x29}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0e,0x91,0xb7,0xa7,0xe2,0xd7,0x05,0x57,0xc6,0x5f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0x10,0xb2,0x07,0x17,0x15,0x3c,0xd9,0xcd,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0f,0x2b,0x55,0x06,0x08,0x78,0x98,0xab,0x3f,0x95}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x08,0xc6,0x58,0x5d,0xf2,0xea,0x02,0x3d,0x96,0x76}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x09,0x3a,0x13,0x09,0xee,0xe3,0x9d,0x4b,0xf6,0x18}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x09,0x96,0x0e,0x33,0xd9,0x24,0xeb,0x3a,0xfd,0x72}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x09,0xf7,0xa3,0x66,0xdb,0x6e,0x04,0xac,0xc2,0x93}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x09,0xdd,0xc5,0x38,0x6f,0x21,0xdb,0xfb,0xc7,0x77}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0x26,0x27,0x21,0xbc,0x8a,0xca,0x0e,0x5a,0x17}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0x2d,0xf9,0x79,0x25,0xf4,0x74,0xc2,0xec,0x54}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0xbf,0x87,0xf8,0x8f,0x6b,0x04,0xb5,0xc3,0xfa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0xc4,0xa9,0xc4,0xd5,0x27,0x6a,0x49,0xa6,0x4a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0a,0xec,0x17,0xfc,0xc5,0x19,0x4a,0x39,0x5f,0x86}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0b,0x6e,0xdf,0x42,0x02,0xef,0x4d,0x56,0xf5,0xcf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0b,0xfe,0xed,0x69,0x75,0x12,0x41,0x62,0x2e,0xb5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0c,0x21,0x88,0x50,0x46,0x4f,0x26,0x23,0xb7,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x0d,0x47,0x96,0x52,0x62,0x81,0x7e,0x6c,0xe5,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0xfd,0x96,0x10,0xc9,0x52,0x1a,0x59,0xb2,0x65}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x17,0x0a,0xdf,0x68,0xcd,0x5c,0xd6,0x68,0xbe,0x75}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x10,0x00,0x45,0xf7,0x04,0x1d,0x50,0xe7,0x43,0x2a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x10,0x21,0xde,0x00,0x2b,0x28,0x62,0xda,0x30,0x63}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x11,0x22,0xd8,0xb2,0x2a,0xee,0x5c,0xcc,0xbb,0x2d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x11,0xe2,0x8f,0x22,0x66,0x48,0x00,0x67,0x17,0x93}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x13,0x45,0x64,0x2b,0x73,0x68,0xf4,0x44,0xb3,0xb9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x15,0x30,0x98,0x3b,0x28,0x23,0x04,0xcb,0x02,0xeb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x15,0xff,0x00,0x68,0xcf,0x86,0x1f,0xf7,0xac,0x7d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x16,0x5f,0xfb,0x18,0x14,0x97,0x0d,0x54,0x3b,0xfa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1e,0x8a,0xde,0xf2,0x25,0xc2,0x46,0x06,0x99,0x1c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1e,0xa4,0xae,0x76,0x9e,0x10,0x3d,0xcc,0x12,0x07}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1e,0xc0,0xeb,0x31,0xa6,0xaa,0xa7,0x2c,0xa0,0x04}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1f,0x51,0x4e,0x01,0x19,0xde,0x34,0xa3,0x08,0xc9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1f,0xb2,0x1b,0x6a,0x57,0x6d,0xcc,0x9e,0xca,0xbb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x18,0x7b,0x11,0xf4,0x9c,0xf4,0xfe,0xc3,0x21,0xa8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x18,0x91,0xa3,0x51,0x6e,0x8a,0xf9,0xcc,0x27,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x18,0xdf,0x33,0xe9,0x96,0x9e,0xe3,0x2a,0xb9,0xc6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x19,0x63,0x6c,0x83,0xe5,0x11,0x04,0xa6,0xb5,0x92}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1a,0x6c,0x74,0x95,0x3c,0x89,0xf6,0xec,0xef,0x09}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1a,0x95,0xd6,0x31,0xe4,0xea,0x66,0x97,0x0d,0x5d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1b,0x93,0xbc,0x99,0x92,0x0e,0x69,0x16,0x40,0xcf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1b,0xc4,0x4e,0x17,0x71,0x14,0x06,0x3c,0x86,0xfd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1c,0x6c,0xed,0xd5,0xb7,0x11,0xfa,0xec,0x94,0x2e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0x10,0xa5,0x20,0x77,0x43,0xf6,0xbc,0x12,0xed}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0x20,0x35,0xa1,0xf3,0x16,0xb4,0x8f,0x1c,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0x30,0xfe,0x09,0xc7,0xe8,0xfe,0xd3,0xee,0x83}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0x33,0xd9,0xd9,0xdb,0xcf,0xc5,0xde,0xae,0xe9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1d,0x69,0xe1,0xac,0x11,0xf1,0x32,0x2f,0x5c,0x8d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1e,0x3d,0x98,0x4b,0x9e,0xc0,0x96,0x40,0x63,0x0f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x1e,0x75,0x81,0xb1,0x3b,0xc4,0x22,0x26,0x72,0x3f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0x83,0xa0,0x76,0x54,0xa8,0xc1,0x6c,0xde,0x83}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0xf6,0x7e,0xfd,0x3a,0x25,0x94,0xa8,0x49,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x27,0x54,0x94,0x03,0x1f,0x7e,0x53,0xd8,0x3f,0x35}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x27,0xd0,0xa7,0x73,0x43,0xd5,0xb2,0x26,0x57,0x1c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x20,0x3c,0x17,0x1f,0x8a,0x74,0xe1,0xdf,0x5a,0x5d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x21,0x47,0x7f,0x18,0x5c,0x97,0x49,0x9c,0x40,0x86}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x21,0x62,0xfa,0x51,0x02,0xf5,0x14,0x4c,0x40,0x52}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x21,0xa3,0x41,0x6c,0x28,0xda,0x27,0x1a,0x78,0xd0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x24,0x45,0xe9,0xa6,0x5a,0xa0,0xb0,0x01,0xaf,0x5b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x25,0x09,0xa6,0xf6,0x4a,0xec,0xd5,0x33,0x74,0x35}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x26,0x55,0x1f,0xca,0x70,0xe5,0xbe,0xe3,0xa6,0x33}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0xdb,0x8c,0x24,0x20,0xf2,0x9f,0x7c,0xb4,0xea}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x28,0x21,0xfd,0xd5,0x3c,0x78,0xa5,0xfd,0xcc,0xf4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x28,0xeb,0x35,0xa7,0x6f,0x90,0x83,0x7a,0x1f,0xfd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x29,0x86,0xfb,0xba,0xbc,0x6e,0x6f,0x53,0x89,0xf5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2a,0x25,0x08,0x7a,0xb9,0x56,0xd9,0xe9,0xeb,0x5d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2a,0x8c,0xfd,0xc2,0xc4,0x30,0x05,0x11,0xe8,0x29}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2b,0xb7,0x31,0x96,0xd7,0xd7,0xe6,0x05,0x42,0x1d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x15,0x79,0x88,0xf6,0xc3,0xd1,0x27,0xa9,0xf5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x28,0xda,0x1d,0x76,0xa8,0xff,0x18,0x78,0x7d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0x6d,0x3e,0xb2,0x42,0x7e,0x0e,0x8a,0x59,0xe4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2c,0xc1,0xc3,0x15,0x28,0xa5,0x7c,0x5d,0x2c,0x9a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2d,0x1d,0x8d,0x21,0xf4,0x84,0x61,0x62,0x74,0x45}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x2e,0x7c,0xd9,0x21,0x3e,0x4a,0x31,0x4b,0x2e,0x42}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x36,0xea,0xb6,0x80,0x00,0x71,0xbb,0x23,0x51,0x1d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x37,0x38,0x8f,0x26,0xd2,0xa4,0xd5,0x66,0x49,0xf9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x37,0x7b,0x3f,0x74,0x7d,0x12,0x92,0x8b,0x89,0xb6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0x12,0x3f,0x13,0x11,0x5e,0xa1,0x65,0x15,0x86}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0x57,0x42,0x6c,0xf1,0xee,0xdf,0xc3,0x46,0xff}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0x5f,0x17,0x76,0x79,0x1d,0x11,0x42,0x97,0x95}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0xb8,0xbd,0xce,0x0b,0xde,0xa0,0x72,0x99,0x88}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0x9a,0xb7,0x46,0xb3,0x7e,0x05,0x40,0x24,0x5e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x30,0xe4,0x80,0xe9,0xaa,0xd1,0x08,0xe4,0x0c,0xc2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0x3a,0x66,0x7c,0x5e,0xb7,0xf0,0x03,0xbf,0x3f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0x0c,0x29,0x90,0x84,0x7f,0x05,0x62,0xcd,0x7d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0x5d,0x88,0x82,0x83,0x35,0x7b,0x04,0x8d,0x54}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0x9e,0x1a,0x61,0xec,0xb9,0x91,0xaf,0x2c,0x5e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x31,0xe0,0x8a,0xe0,0x9f,0x11,0x44,0xa4,0x49,0xb3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x32,0x22,0x05,0x5d,0xcc,0x69,0x3a,0x50,0xe3,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x32,0xf3,0xd3,0x15,0x5b,0xdc,0xe9,0x43,0x75,0xa4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x33,0xd6,0x09,0xdd,0xd8,0x37,0x5b,0x75,0xf6,0x29}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x34,0x50,0xf5,0xf6,0xe9,0xb6,0x34,0x31,0x47,0xc2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x34,0xce,0x7c,0xad,0x90,0x12,0x35,0xa6,0xde,0x34}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x34,0xdd,0xa1,0xfb,0x92,0xb3,0xa4,0x56,0x2b,0xc2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x35,0x00,0x24,0x34,0x98,0xee,0x98,0x61,0x05,0xfa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x35,0x95,0x33,0x45,0x93,0xb2,0xbc,0xda,0xf6,0x42}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x35,0x9d,0x76,0xb9,0x43,0x15,0x85,0xf3,0xe3,0x8f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3e,0xf7,0xb2,0xf2,0x0d,0xb1,0x3e,0xc8,0xe1,0x8d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3f,0x81,0xbd,0x37,0x81,0x58,0x6d,0x6c,0x37,0x83}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x0b,0x69,0xc4,0x2e,0x74,0xb2,0xe2,0x30,0x2c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0x6c,0x73,0x48,0x3b,0x21,0x10,0xd6,0xc7,0xd3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xab,0xe2,0xba,0xe7,0xeb,0x15,0xf2,0x9c,0x3d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xfc,0x75,0x4c,0x4b,0xf5,0x80,0xcc,0xaf,0x2c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xc1,0xe6,0x48,0x1c,0xaf,0x23,0x3f,0xfc,0xd7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x38,0xcc,0xdb,0xaa,0x90,0x90,0xfd,0x64,0xda,0xd7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x39,0x8f,0xb0,0x65,0xbb,0x21,0x24,0x31,0xd4,0x46}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x39,0xf1,0x7a,0x78,0x36,0x52,0x48,0x52,0x25,0xd9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3a,0x32,0xdf,0x45,0x8e,0x2c,0x8d,0xba,0x3d,0x8d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3a,0x61,0x7b,0xcb,0x1a,0x74,0x88,0xc2,0xd4,0x95}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3a,0x82,0xff,0xb0,0x26,0xb7,0x94,0xb5,0xcb,0x92}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3a,0xdc,0x9a,0x59,0x16,0x0a,0x9c,0x9e,0x28,0x79}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3a,0xf3,0x79,0x26,0x3f,0x70,0x77,0x0c,0xe6,0x10}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3b,0x51,0x4c,0xbd,0x64,0xc9,0x03,0x83,0xd7,0xe0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3b,0x9a,0x32,0x59,0x49,0xe4,0xb9,0x11,0x8a,0xc5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3c,0x17,0xd6,0xd7,0xd5,0x38,0x88,0x81,0xec,0x2d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3c,0x9e,0x97,0x7d,0x90,0x8c,0x49,0xd3,0x62,0xf1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3d,0x3d,0xc9,0x69,0x83,0x8e,0xef,0xfc,0x5d,0x40}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3d,0x6d,0x58,0x6a,0x56,0x54,0x2d,0xb8,0x57,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3d,0x9d,0xa0,0xa3,0x0d,0x1c,0x63,0x57,0xaf,0xc5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x3e,0x6e,0x9d,0x8e,0x67,0xde,0x35,0x79,0xf3,0xae}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x46,0xe8,0x5b,0xd2,0xdb,0x9f,0xc5,0x72,0x8d,0xf0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x40,0x36,0xdd,0xc3,0xb4,0xe7,0x4d,0x57,0xdf,0xe0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x40,0x8a,0x69,0x6c,0xa2,0x98,0x94,0x3e,0x60,0x8e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x40,0x9f,0x9f,0x4c,0xf0,0xa8,0xd2,0x2b,0x2e,0xa1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0x77,0xac,0xbb,0xb4,0xe3,0x0e,0x3a,0x34,0xa3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0xb8,0xb3,0x52,0x0b,0xf5,0x6e,0xa0,0xb1,0x91}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x41,0xce,0x28,0xfc,0xa7,0x16,0x60,0x30,0x0b,0x98}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x42,0x59,0xa9,0xe2,0xee,0x0f,0xea,0xaa,0x83,0x39}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x43,0xf6,0xfa,0x52,0x06,0x3d,0x18,0x5c,0xf6,0xd6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0x36,0xa2,0x4f,0xfa,0x2e,0xf1,0xa2,0xc5,0xe6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x44,0x00,0x69,0xf4,0x4e,0xe0,0xe7,0xf3,0xf8,0xe5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0x0d,0x6e,0x69,0x07,0xf1,0xdf,0x18,0x47,0x5e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0x4b,0xff,0xf2,0xbc,0x9f,0xd5,0xed,0xa3,0xc3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0x4a,0x01,0x0c,0xbf,0x12,0x0d,0xac,0xeb,0x1a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0x65,0x71,0xd9,0x54,0xeb,0x8d,0xac,0xa7,0x8b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x45,0xec,0x68,0x9c,0x0a,0x5d,0x69,0xc3,0x79,0xdf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x46,0x7b,0xe6,0x39,0xde,0x62,0x9f,0xb3,0x7e,0xee}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x84,0xfe,0xb2,0x96,0xea,0x76,0xba,0x30,0x57}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x97,0x15,0x46,0xd4,0x32,0xc7,0x62,0x5a,0xd2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0xa1,0x36,0x28,0x7a,0x18,0x02,0xb9,0x4b,0x3c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4f,0x49,0xac,0x50,0x0d,0xef,0xeb,0xa3,0xf4,0x8b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4f,0x52,0x58,0x8e,0x67,0x84,0xfa,0x6d,0x76,0xf9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4f,0x56,0xad,0x52,0xba,0x0c,0x9e,0x58,0x5c,0xaa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x48,0x1b,0x5a,0xe6,0x4c,0xc8,0xa4,0x9d,0x95,0x0b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x49,0x1a,0xdd,0x4d,0x98,0x5e,0xef,0x70,0x45,0x90}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x49,0x5c,0x4e,0x97,0x52,0x16,0x5c,0x92,0xbf,0x7a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x49,0x84,0x64,0x79,0x5a,0x7d,0xdc,0xe4,0x76,0x1b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x49,0xc0,0xd0,0x6b,0x92,0xd8,0xf2,0xa4,0x4f,0x2f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4a,0x26,0x6a,0x2c,0x3a,0xe3,0x2a,0x58,0x44,0x66}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4a,0x69,0x5b,0x05,0x25,0xca,0xd2,0xc6,0xfe,0x7b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4a,0xc4,0x57,0x30,0xd1,0xed,0xca,0x4b,0x81,0x05}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4a,0xc8,0x79,0x7b,0x01,0x0e,0xbd,0x05,0xb5,0xa0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4a,0xd3,0x9c,0xf2,0x6c,0x0c,0x23,0x78,0x6e,0x1d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4b,0x85,0xc7,0x40,0x44,0x20,0xd4,0x6f,0xfe,0xa5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4c,0x7b,0x8f,0x35,0x34,0x08,0x83,0x5f,0x1b,0x7f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4c,0x5c,0x07,0x4b,0xcb,0x07,0x2a,0x82,0x1d,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4c,0x98,0xf3,0x99,0x40,0xc7,0xd0,0x83,0x85,0x51}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4c,0xd5,0x26,0xb9,0x54,0x90,0x72,0xc9,0x7e,0xcb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0x3a,0x3a,0x3b,0x71,0xf3,0xfc,0x34,0x65,0xa2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xbd,0x9c,0x32,0xe2,0x69,0x02,0x03,0xd2,0x89}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4d,0xc0,0xba,0x9c,0xbf,0xb7,0xec,0x4a,0xc3,0x36}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x32,0x72,0x6d,0x06,0xe7,0x10,0x25,0x62,0x41}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x4e,0x49,0xea,0x29,0xbc,0x40,0xe2,0x7e,0x70,0x8e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x57,0x0c,0xb7,0x4d,0x77,0x6b,0x27,0x30,0xf8,0x53}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x57,0xe9,0x8d,0xa2,0xcc,0xa9,0xa9,0x9c,0x18,0x7a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x52,0xf5,0xb7,0x14,0x06,0xdd,0x14,0x1f,0x1e,0xeb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x53,0x95,0x3d,0x42,0x3e,0x1f,0x1e,0xcc,0x07,0x43}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x53,0xc0,0xba,0x6c,0xfd,0xc0,0xd4,0xe0,0x22,0xb2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x54,0x46,0xf0,0x8e,0xb3,0x85,0xba,0x2e,0xac,0x84}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x54,0x51,0x6f,0x2b,0x29,0xc8,0x23,0x93,0x07,0x66}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x54,0x5f,0xa9,0x9c,0x4c,0xb4,0x5f,0x27,0x50,0x9e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x55,0x71,0x51,0xd9,0x36,0x98,0x09,0xd6,0x3b,0xff}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x56,0x23,0x78,0xa3,0xb1,0x0c,0x7c,0x87,0xd2,0x32}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x56,0x76,0xeb,0x9b,0xff,0xe7,0x47,0x79,0xfb,0x50}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5e,0xed,0xd2,0x89,0x48,0xd5,0x83,0x17,0x6a,0x01}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5f,0x38,0x14,0x4a,0x97,0x39,0xff,0x12,0x07,0xb0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5f,0x7d,0xd3,0x77,0x5b,0x23,0x12,0x40,0xd2,0x49}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5f,0xad,0xd5,0x0c,0x88,0x35,0xa4,0x66,0x97,0xb3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5f,0xc1,0xc2,0x32,0x38,0x2d,0xd4,0x93,0x31,0x81}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5f,0xe4,0xb7,0x48,0x49,0x84,0x02,0x82,0x8a,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x58,0x00,0x54,0xc2,0xb3,0x71,0xbe,0x34,0x95,0x7a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x58,0x0f,0xef,0xf9,0x57,0x09,0x82,0x6b,0x6e,0x9a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x58,0x61,0xa0,0x7d,0xed,0x7b,0x2a,0x8b,0x6a,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x58,0xb9,0x66,0xbe,0x0b,0xd7,0xeb,0x86,0x23,0x7d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x58,0xdc,0x52,0x84,0xaf,0x56,0xd3,0xe1,0x7f,0x1f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x0e,0xf6,0x19,0x6a,0x45,0x5c,0x18,0x6a,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x89,0x67,0xa7,0x3f,0x41,0x3e,0x30,0x42,0x11}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x59,0x95,0x50,0xd6,0x2e,0xf7,0xd2,0xe6,0x3a,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5a,0x2d,0xdc,0xf1,0xa6,0x40,0xbc,0x1f,0xd5,0xb5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5a,0x65,0xf3,0x5a,0x2c,0x66,0x41,0xe8,0x78,0xc0}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5b,0x2a,0x0b,0xec,0x9e,0x05,0x81,0x7a,0x9e,0x08}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5c,0x73,0xff,0x8e,0xc5,0xfe,0x21,0xc1,0x19,0xb3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5d,0x41,0xde,0x3d,0xa1,0x86,0x9b,0x26,0x27,0x11}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5d,0xc5,0xaa,0x3c,0xf7,0xc6,0x2e,0x55,0x9d,0xa5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5e,0x13,0x80,0x8e,0x3c,0x3b,0x13,0xb0,0xc0,0x01}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x5e,0x75,0x95,0xb5,0x98,0xc3,0x6d,0x33,0x58,0xba}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x67,0x8e,0x26,0xbd,0x0a,0x43,0x30,0x7d,0xff,0x0f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x60,0xfd,0xbe,0xb9,0x89,0x6c,0x4c,0x72,0x10,0x7b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x60,0xc3,0xb7,0x51,0xf6,0x2f,0x0b,0xa8,0x61,0x21}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x61,0x3c,0x3e,0x12,0x57,0xfb,0x8e,0x36,0xdd,0xa4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x61,0x04,0x55,0x21,0x5d,0x12,0x39,0xfb,0x09,0x49}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x61,0x63,0x52,0x55,0xbf,0xb7,0xa3,0x69,0x3f,0x91}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x62,0x19,0x4a,0x4d,0x64,0xb7,0x65,0x19,0x8e,0x8a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x63,0x71,0x25,0x6d,0x19,0xbd,0x62,0x0d,0x9e,0x95}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x64,0x29,0xe3,0x42,0x71,0x3b,0x3d,0x7c,0xda,0xc7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0xa8,0x2f,0x55,0xcc,0xe3,0x4c,0x84,0xcc,0x3b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x65,0xc7,0x38,0xa4,0xe4,0xd6,0x0b,0x2b,0xed,0xe6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0x10,0x12,0x4f,0x8f,0x44,0x85,0x5d,0x69,0xa9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0x87,0xcf,0x54,0x39,0xbf,0x36,0x12,0x55,0x61}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0xa7,0xe5,0x14,0xd9,0x5d,0x5d,0x9b,0x9c,0xac}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6f,0xe3,0x17,0x08,0xf6,0x24,0x4b,0xa8,0x5f,0x24}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x68,0xa4,0x34,0x41,0x8d,0xb9,0xda,0xd4,0x86,0x59}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x27,0x7b,0x6d,0x0b,0x29,0x5a,0x67,0xd1,0x95}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x57,0x2a,0xd0,0x28,0x58,0xc8,0x75,0xd2,0xd1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x64,0xb2,0xc9,0x15,0xc6,0x0e,0x8b,0x86,0x4f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x8b,0xd2,0x78,0x3f,0x7a,0xf8,0x92,0x8f,0x80}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0x9e,0xf9,0x07,0x73,0xd8,0xe8,0x24,0x93,0xcc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0xcb,0x6c,0x41,0x52,0x61,0x20,0x4e,0x77,0x39}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6a,0xf0,0x96,0x3c,0x4c,0x78,0x33,0xd0,0xf0,0x00}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6b,0x59,0x5f,0xe7,0xdd,0x57,0xba,0xc1,0x12,0x51}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6c,0x62,0x5b,0x0d,0x91,0x66,0xd0,0xca,0x10,0x2d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6c,0x62,0xc5,0x19,0x94,0x5b,0xcd,0x20,0xd9,0x73}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6d,0xb8,0x7f,0xac,0x82,0x55,0x27,0xf2,0x01,0xf5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6d,0x95,0x8d,0xd8,0x7b,0x41,0xdc,0x81,0xd4,0x3d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x6e,0x38,0xa5,0x11,0x8c,0x64,0x2b,0xc5,0xbe,0x6c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x76,0xbb,0x65,0x0a,0xdf,0x23,0xa2,0x6d,0x4d,0xc8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x76,0x8d,0x46,0x54,0x2a,0xb7,0x9e,0xce,0x74,0x45}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x77,0x30,0x99,0x1c,0x76,0x58,0x64,0x7c,0x2e,0x16}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x71,0x6f,0xc8,0x1a,0xde,0x5b,0xde,0xda,0xcc,0xd5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x72,0x89,0x34,0x3d,0x7c,0x33,0x47,0x01,0x02,0x92}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x74,0x3b,0x0e,0x42,0x30,0x42,0x63,0xa5,0x3e,0x8d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x74,0x2d,0xb6,0x15,0xc8,0x70,0x60,0x25,0x2e,0xe7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x74,0x65,0x8d,0x57,0xdb,0x20,0xa2,0xc1,0xa7,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x74,0xf9,0x3c,0xb3,0x2d,0xc2,0x18,0xc5,0xcb,0x2a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x75,0x95,0xe1,0x69,0x25,0x99,0xec,0xac,0x00,0xe4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x76,0x3f,0x29,0x6c,0xec,0xd3,0x95,0x7e,0x4e,0x8d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7e,0x9e,0x2f,0x58,0x20,0x23,0xea,0x34,0x78,0x44}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7e,0xaf,0xae,0x18,0x67,0x04,0x98,0x61,0x2f,0xa9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7f,0x84,0xea,0x51,0x31,0xd3,0x46,0x75,0xae,0xbb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x3e,0x3b,0x74,0x2b,0x6f,0x57,0x06,0x53,0xbb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0x24,0xc1,0x1e,0x6e,0x73,0x93,0xa5,0x08,0xe3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x78,0xc0,0xf5,0x28,0xea,0xf3,0xc2,0x2c,0x6a,0x69}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x79,0x0f,0xd0,0x25,0xd4,0xa5,0xbc,0xcb,0x72,0x51}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7a,0xa9,0x41,0x75,0xf6,0x5f,0x6f,0x83,0x58,0xf1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0x39,0x64,0xaf,0xf5,0x37,0xe7,0x22,0xe0,0x42}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0xc3,0x68,0x1e,0x92,0x7c,0xbb,0x04,0x12,0x0b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7c,0xec,0xf0,0xdb,0x09,0xea,0xdb,0x82,0x5b,0x45}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7d,0x3f,0x6d,0xa4,0xb8,0x8e,0x5f,0xf9,0x5e,0x48}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x7d,0xb0,0xb0,0xe2,0xa5,0xa0,0xbd,0xa3,0x9e,0xb7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x86,0x8a,0x76,0xb7,0x13,0xe8,0x74,0x0c,0x54,0x44}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x86,0xd1,0xb0,0x3e,0x88,0x73,0x42,0x0c,0xb0,0xa4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x80,0xfc,0x51,0x3e,0x9b,0x7d,0x42,0x5d,0x63,0x77}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x81,0x49,0x6a,0xef,0x1f,0x06,0xdf,0xc4,0x6c,0x23}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x81,0xf1,0x31,0xce,0x65,0x59,0xc2,0x2e,0x46,0x47}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0x9b,0xbe,0xc4,0x3b,0xbe,0x8d,0x70,0xda,0x1c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x82,0xea,0xb2,0x5e,0x5f,0x7d,0x80,0x2d,0x17,0x81}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x83,0x8c,0x28,0x22,0x33,0xa4,0xc1,0xe8,0xae,0xe6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x84,0x73,0x02,0xdd,0x47,0x8b,0x29,0xda,0xf6,0x2e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x84,0xb0,0x90,0x4a,0x1c,0xf0,0x75,0x2c,0x23,0x12}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0x29,0xc0,0xeb,0x29,0x0b,0x63,0xaa,0x13,0x98}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0x30,0x22,0xa7,0x56,0x23,0x73,0xe0,0x97,0x03}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0x47,0x8d,0x89,0x8e,0x13,0x57,0x5e,0xd7,0xe2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x85,0x6c,0x77,0xc3,0x06,0x03,0x75,0x75,0x63,0xa7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x86,0x29,0x3b,0x0b,0x5e,0xa2,0xd7,0x44,0x80,0xa1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8f,0x3b,0x03,0x68,0x7e,0x45,0x8a,0x33,0xc2,0xcb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8f,0x2f,0x41,0xc7,0xd4,0xe4,0x7a,0xdc,0x18,0x1c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8f,0x80,0xf0,0x76,0x52,0xa2,0x6e,0x1b,0x0f,0x7c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8f,0xb3,0xa3,0x0a,0x54,0xdf,0xd5,0xb3,0x00,0x07}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x88,0x62,0x93,0x14,0x42,0x07,0xab,0xd0,0xff,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x88,0x90,0x5b,0xa0,0x20,0xb4,0x27,0xe8,0xdf,0x39}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x88,0xdd,0xbb,0x8a,0x6a,0xde,0x55,0x94,0xd5,0x6d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x88,0xea,0xb2,0x3f,0x1e,0x31,0xcc,0xf0,0x3f,0x2e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x89,0x05,0x2d,0x83,0x5f,0x11,0xeb,0xa5,0x9b,0xdd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x89,0x58,0x14,0x63,0xb5,0xcc,0xea,0xdf,0x1f,0x0d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8a,0xd1,0xd5,0x85,0x24,0xe2,0xbf,0xf4,0x37,0x36}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8b,0xa1,0x66,0xb0,0x8f,0x12,0x79,0xdd,0xd4,0xa7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8b,0xc2,0xdb,0xf7,0x90,0x6a,0x11,0x58,0xb0,0xfb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8c,0xab,0x57,0x1a,0x03,0x5a,0x12,0xff,0xfc,0xf5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x8d,0x99,0xd1,0xf0,0xe6,0xd9,0xc5,0xff,0xa8,0x73}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x96,0xf0,0x45,0xaa,0xa2,0xe9,0x7b,0x72,0x62,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x97,0xa3,0x7e,0xe8,0xe8,0x9b,0x1e,0xfe,0x2c,0xc4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x90,0x3c,0xcd,0xc6,0xb8,0x12,0x1e,0x62,0x31,0x58}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x90,0x2a,0x40,0x90,0x92,0x62,0x91,0x56,0x14,0x2e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x90,0x70,0x98,0xf5,0xaf,0x56,0x98,0xb6,0x16,0xdf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x91,0x23,0x64,0xf3,0x49,0x61,0x3b,0x73,0x9d,0x96}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x91,0xb9,0x56,0x50,0x35,0xd8,0xd3,0x1c,0xd6,0x87}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x91,0xe4,0x65,0x49,0x74,0xcf,0x92,0xa3,0x3f,0xc6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x92,0x71,0x96,0x5a,0xd4,0xf0,0xd0,0x84,0x4f,0x71}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x92,0xb6,0x46,0xee,0x24,0xa0,0xcd,0xb9,0x0c,0xdd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x92,0x9c,0x82,0xbf,0x8e,0x4f,0xd7,0xc7,0x4a,0x9d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x92,0xc9,0xa1,0x01,0xeb,0x52,0xdb,0xbd,0x93,0xf8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x93,0x06,0x3f,0xc3,0xe6,0x73,0x40,0x91,0xb1,0x30}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x93,0xd8,0x7a,0x5d,0x21,0xd0,0x87,0xf5,0x92,0x8d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x94,0x54,0x6c,0x57,0xa4,0x1b,0x74,0xf0,0x7d,0x0b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x94,0x96,0xd4,0xa4,0xed,0x65,0x96,0xbc,0x4a,0xbc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x95,0x3d,0xec,0x1a,0x20,0x97,0xa2,0xa1,0xcd,0xab}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x95,0x1a,0x3a,0xb0,0x29,0x8c,0xcc,0x32,0x80,0xf7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x95,0x47,0xee,0xab,0xa9,0x78,0x17,0xa7,0xed,0x73}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x95,0x68,0x0e,0x9d,0x10,0x5d,0x2d,0xf7,0x6a,0x56}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x95,0xe0,0x9a,0x05,0x94,0x67,0x22,0xc2,0x99,0xf4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9e,0xb9,0xda,0xa3,0xfc,0xd4,0xd1,0xb9,0xb5,0x40}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9f,0x0a,0x17,0x56,0xa6,0xcb,0xda,0x86,0x0f,0x4f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9f,0x17,0xcb,0x57,0x64,0x8a,0x8e,0xf1,0x93,0x4f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9f,0x60,0x23,0xd8,0x31,0xf5,0x3b,0x5d,0x00,0xca}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9f,0xd2,0xb0,0x27,0xc6,0x36,0x2f,0xf9,0x76,0xb8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x3d,0x24,0x92,0x18,0x0e,0xbe,0x5e,0x37,0x80}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x2b,0xfa,0x4d,0xf6,0xe3,0xcb,0x8f,0xa7,0xca}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x98,0x2e,0x6e,0xe7,0x52,0xb9,0x59,0xd1,0x70,0x7e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0x15,0x6a,0xb4,0x2e,0x18,0x73,0x15,0xd0,0xb2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xb9,0x4b,0x45,0x2c,0x9c,0x74,0x95,0x85,0x38}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xf8,0x24,0xd4,0xa5,0x4c,0xed,0xea,0xb9,0x94}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xfc,0x5b,0xe1,0x93,0xb3,0x4a,0x82,0xc0,0x94}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x99,0xe6,0x23,0x9d,0x7a,0xed,0x35,0xe6,0x99,0x70}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9a,0x10,0x03,0xfc,0x52,0xa3,0x94,0xb1,0x55,0x1e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9a,0xbd,0xbb,0xf4,0xaa,0xde,0xf7,0xfc,0xee,0x83}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9a,0x8c,0xe7,0x4c,0x13,0xf0,0xa0,0xdf,0xd7,0x18}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9b,0x53,0xdf,0x76,0xd6,0x86,0x7b,0x67,0xa6,0xb2}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9c,0xbd,0x0b,0xef,0xec,0x63,0xe9,0xe6,0xa7,0xb8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9c,0xd2,0x89,0x56,0xf8,0x19,0x83,0x37,0xf7,0xc5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9d,0x9b,0xde,0x57,0xf1,0x06,0xae,0x93,0x0f,0xbd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9d,0xc8,0xce,0xb0,0x94,0x36,0xb8,0x6d,0x13,0x23}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9e,0x11,0x46,0xb7,0x7e,0x5b,0x0a,0x28,0x75,0x71}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0x9e,0x2b,0xdf,0x5e,0x5e,0x37,0x9a,0x3c,0xc2,0x97}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0x3e,0x5d,0x9e,0xf6,0x87,0xbb,0x23,0x4b,0x8e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0x23,0xf2,0xb4,0xee,0x5c,0x47,0x6b,0x2d,0xa8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0x7b,0xe7,0x14,0x3b,0x66,0x01,0x10,0x16,0xcd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa7,0x61,0xb3,0x07,0x3c,0x83,0xf3,0xcb,0x55,0x71}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa0,0x14,0xbc,0x6f,0x03,0x89,0x2b,0x57,0xde,0xc8}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa1,0xbc,0x70,0x3d,0x1c,0x84,0xc8,0xac,0x8b,0xf5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa2,0x3b,0xdd,0xc1,0xd3,0x1f,0xa2,0xe6,0xee,0x25}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa2,0x23,0xf2,0xee,0xcb,0x9b,0x94,0x0f,0x04,0x21}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa2,0xa2,0x94,0x9e,0xce,0x1a,0xf9,0xcb,0x31,0xc5}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa2,0xfa,0x66,0x69,0x17,0xc7,0xd5,0x01,0x96,0xc6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa3,0x46,0x3f,0xc6,0x49,0xe3,0xc8,0xdd,0xd9,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa3,0xa3,0x67,0xe4,0xa4,0x3c,0xf0,0xa8,0x9b,0x9b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa3,0xab,0x27,0xeb,0x0b,0x9b,0x40,0xe4,0xc3,0xcb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa4,0x81,0x96,0x0c,0x52,0xde,0x9b,0x8d,0x70,0x78}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa4,0x81,0x99,0x7c,0xcb,0x67,0xcc,0x4c,0x5d,0x4b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa4,0xa5,0xa5,0x10,0x66,0xfc,0x15,0x63,0x0e,0x3d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa4,0xcd,0x88,0xd6,0xdf,0xed,0xab,0xa6,0xe1,0x88}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa6,0x6c,0x01,0x32,0x5f,0x56,0x32,0x72,0x1c,0x2b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xae,0x94,0x31,0x12,0x75,0x92,0xd8,0x32,0x8a,0xd1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaf,0x56,0x76,0xe7,0x35,0xf3,0x5a,0x62,0x9b,0xa3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa8,0xb9,0xc3,0x07,0x95,0x23,0xde,0xe0,0xc6,0x7b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa9,0x6d,0x83,0xa6,0x9c,0xdd,0xae,0x7c,0xd6,0x97}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa9,0xa8,0x9a,0x15,0x5d,0xda,0xe1,0x87,0x2d,0x0e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xa9,0xc8,0x44,0xc2,0x1a,0xaf,0x46,0xa0,0xf2,0xf1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xaa,0x7d,0xc2,0x0c,0x95,0xe2,0x5b,0x02,0x8e,0x41}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0x00,0x8e,0xd1,0x06,0x26,0x63,0xa5,0x1d,0x49}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0x29,0x85,0x0f,0xf2,0xb8,0x58,0x8f,0xdb,0xbf}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0x98,0x40,0x0a,0x73,0x43,0x6f,0xb6,0x3d,0x8b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xab,0xdd,0x6d,0x5d,0xc5,0x36,0xcb,0x6c,0xc8,0x70}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xac,0x81,0x65,0xa3,0x8b,0xea,0x0b,0x71,0xe4,0x16}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xad,0x1b,0x40,0xc1,0x45,0x64,0xbf,0x24,0x15,0xca}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xad,0x1c,0xc0,0xb4,0x95,0xb5,0x17,0xc0,0xc2,0x41}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xad,0xc4,0xfa,0x8d,0xa6,0xf7,0x40,0x42,0xe7,0xd3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xae,0x2e,0xe4,0x64,0x79,0x05,0x5f,0xb7,0x04,0x14}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb0,0x48,0xe6,0xe8,0x48,0xfa,0xca,0x87,0x78,0x18}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb0,0x6c,0x4a,0x92,0xde,0xd3,0x0d,0x28,0xc4,0x79}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0x41,0x81,0xac,0xde,0xce,0x0b,0x94,0x8a,0x9d}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0x73,0xdf,0x4b,0xab,0xc3,0x7a,0x3c,0x48,0x99}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0xb6,0xc8,0x72,0x86,0xc6,0x34,0x6b,0xef,0x41}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0xd5,0x8e,0xf0,0x22,0x9a,0x8b,0xa6,0xf1,0xfb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb1,0xd8,0x90,0x36,0x0e,0xc6,0x51,0x9c,0x8b,0x93}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb2,0xce,0xea,0x6a,0xd7,0x34,0x30,0x8d,0xdf,0x65}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb2,0xea,0xa2,0xc5,0xeb,0x2a,0x10,0xec,0xeb,0x4e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbe,0xda,0x60,0xee,0xa0,0xf8,0xdd,0x5a,0x11,0xb6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbf,0x7f,0x7f,0x68,0x2c,0x63,0x70,0xba,0xbb,0xf1}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb9,0xaa,0xce,0xfd,0x87,0x35,0x7b,0xee,0x0d,0x40}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xb9,0xe5,0xb3,0x2c,0xb6,0x6d,0x91,0x46,0x22,0xad}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xba,0x49,0xd2,0xda,0xb8,0x28,0xe8,0x4d,0x53,0xca}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xba,0xcd,0x40,0x9b,0x0b,0xc6,0x82,0xba,0xc8,0xdd}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbb,0x57,0x4d,0xce,0xa0,0x53,0x4d,0x8f,0xcd,0x4f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbb,0xba,0xc0,0x45,0x0b,0x3d,0x30,0xef,0x86,0x93}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbc,0x80,0x0b,0xa0,0xe3,0xc1,0x9b,0x6b,0xc5,0x17}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbd,0x3a,0xc5,0xd0,0xc3,0x93,0x32,0x55,0x57,0x27}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbd,0x63,0x78,0x09,0xf3,0x85,0x50,0x42,0x0c,0x3a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xbd,0xb2,0x78,0xc7,0x06,0x2c,0xe1,0xb8,0x72,0xdc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc7,0x25,0x66,0x48,0x17,0x18,0x9d,0x2d,0x05,0xb4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc7,0x66,0xbe,0x2e,0x08,0xdf,0xba,0xf7,0xae,0x83}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc7,0x6d,0x92,0x43,0x00,0x24,0xe5,0xd6,0x83,0xd3}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc7,0xf7,0x05,0x69,0x99,0x52,0x54,0x77,0x2b,0x1f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc7,0xdd,0x9d,0xe0,0x6d,0xaa,0x03,0xcb,0x9c,0x21}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc0,0x0f,0xf8,0x18,0xb0,0x84,0x66,0x47,0x08,0xe4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc0,0x41,0xc0,0xc5,0x9d,0xef,0x46,0x46,0xae,0x7f}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc1,0x89,0x05,0x1b,0x88,0x6b,0xd7,0x20,0x08,0x9b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc2,0x4e,0xd2,0xd3,0xfd,0x58,0x32,0x14,0x6f,0x87}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc2,0x6d,0xf5,0x40,0x0f,0xbd,0xfb,0x53,0x19,0xc9}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc3,0x3e,0x86,0xb1,0xd5,0x0c,0x5a,0x0e,0x18,0x4e}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0x3a,0x2a,0x49,0xb4,0x72,0xa4,0x2c,0x7b,0x99}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0x44,0x04,0x3a,0x11,0x84,0x47,0x67,0x2a,0x13}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0x45,0x1f,0xbc,0xc9,0xa0,0x32,0x01,0xeb,0xbc}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0x55,0x2a,0xb9,0xbb,0x9b,0x2a,0xe7,0x1c,0x75}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0xdf,0x49,0x72,0xb7,0xed,0xbe,0x9f,0x59,0xfa}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc4,0xe0,0x24,0x19,0x5a,0x39,0xc6,0xbe,0x74,0xee}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc5,0xdc,0x95,0xee,0xec,0x4d,0x25,0xb1,0xa1,0x5a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc6,0x47,0x01,0xca,0x17,0xe1,0x47,0x46,0x9b,0xd6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0xf6,0xda,0x2a,0x7f,0x69,0x90,0xad,0x89,0xe4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0xf1,0x60,0x80,0x76,0xe7,0x9a,0x36,0xdc,0xc7}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcf,0x98,0x18,0x43,0xeb,0x5d,0xd7,0x16,0xf1,0x50}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc8,0x76,0xb8,0x89,0x52,0x6f,0x23,0x93,0xe5,0x24}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc9,0x3e,0xe1,0xbf,0xef,0xc8,0x22,0x97,0xae,0x51}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc9,0x82,0xc3,0xcc,0x29,0x07,0x0b,0x8d,0x6f,0xfb}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xc9,0xfe,0x7a,0x81,0x62,0x35,0x52,0xf7,0x02,0x0c}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xca,0x33,0x3a,0xdc,0x87,0x62,0x7a,0xc2,0x1d,0xe6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xca,0x50,0x8d,0xe0,0x82,0x1c,0x59,0x0f,0xef,0x1b}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xca,0xa3,0x66,0x19,0x34,0xac,0xb2,0x0f,0x60,0x9a}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcb,0xb3,0xa0,0x39,0xf6,0x46,0xec,0x5a,0x42,0xc6}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcc,0xc6,0x22,0xb4,0xfc,0xf7,0xff,0xb0,0xa2,0xb4}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcd,0x2e,0x71,0x78,0x7b,0x6d,0x9e,0x61,0x70,0x05}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcd,0x31,0x38,0x94,0x95,0xca,0x44,0xf4,0x65,0x68}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcd,0x61,0xe1,0xbe,0x7b,0x46,0x9c,0x51,0xbf,0x66}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xcd,0xac,0xcf,0x18,0x1f,0xa6,0x8f,0x02,0x6a,0x43}, 8333},
+ {{0xfd,0x87,0xd8,0x7e,0xeb,0x43,0xce,0x20,0x1e,0x2c,0x8d,0x2c,0x9e,0xd9,0xa7,0xac}, 8333}
};
static SeedSpec6 pnSeed6_test[] = {
diff --git a/src/clientversion.cpp b/src/clientversion.cpp
index 993967a180..aaf041602b 100644
--- a/src/clientversion.cpp
+++ b/src/clientversion.cpp
@@ -30,8 +30,7 @@ const std::string CLIENT_NAME("Satoshi");
#define BUILD_DESC BUILD_GIT_TAG
#define BUILD_SUFFIX ""
#else
- #define BUILD_DESC "v" STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) \
- "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+ #define BUILD_DESC "v" STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD)
#ifdef BUILD_GIT_COMMIT
#define BUILD_SUFFIX "-" BUILD_GIT_COMMIT
#elif defined(GIT_COMMIT_ID)
@@ -45,10 +44,7 @@ const std::string CLIENT_BUILD(BUILD_DESC BUILD_SUFFIX);
static std::string FormatVersion(int nVersion)
{
- if (nVersion % 100 == 0)
- return strprintf("%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100);
- else
- return strprintf("%d.%d.%d.%d", nVersion / 1000000, (nVersion / 10000) % 100, (nVersion / 100) % 100, nVersion % 100);
+ return strprintf("%d.%d.%d", nVersion / 10000, (nVersion / 100) % 100, nVersion % 100);
}
std::string FormatFullVersion()
diff --git a/src/clientversion.h b/src/clientversion.h
index 363094b696..c925b8f084 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -10,7 +10,7 @@
#endif //HAVE_CONFIG_H
// Check that required client information is defined
-#if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_REVISION) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR)
+#if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR)
#error Client version information missing: version is not defined by bitcoin-config.h or in any other way
#endif
@@ -36,9 +36,8 @@
#include <vector>
static const int CLIENT_VERSION =
- 1000000 * CLIENT_VERSION_MAJOR
- + 10000 * CLIENT_VERSION_MINOR
- + 100 * CLIENT_VERSION_REVISION
+ 10000 * CLIENT_VERSION_MAJOR
+ + 100 * CLIENT_VERSION_MINOR
+ 1 * CLIENT_VERSION_BUILD;
extern const std::string CLIENT_NAME;
diff --git a/src/compat.h b/src/compat.h
index 0be02cae03..5fa6589792 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -18,11 +18,7 @@
#undef FD_SETSIZE // prevent redefinition compiler warning
#endif
#define FD_SETSIZE 1024 // max number of fds in fd_set
-
-#include <winsock2.h> // Must be included before mswsock.h and windows.h
-
-#include <mswsock.h>
-#include <windows.h>
+#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdint.h>
#else
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 932f0d2c60..0983595c6a 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -79,7 +79,9 @@ struct Params {
int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan;
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
+ /** The best chain should have at least this much work */
uint256 nMinimumChainWork;
+ /** By default assume that the signatures in ancestors of this block are valid */
uint256 defaultAssumeValid;
/**
diff --git a/src/core_io.h b/src/core_io.h
index 80ec80cd50..aaee9c445d 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -22,8 +22,8 @@ class UniValue;
// core_read.cpp
CScript ParseScript(const std::string& s);
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
-NODISCARD bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
-NODISCARD bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
+[[nodiscard]] bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
+[[nodiscard]] bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
bool DecodeHexBlockHeader(CBlockHeader&, const std::string& hex_header);
/**
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 121e62457c..7687a86185 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -15,16 +15,15 @@
#include <version.h>
#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <algorithm>
#include <string>
-CScript ParseScript(const std::string& s)
-{
- CScript result;
+namespace {
+opcodetype ParseOpCode(const std::string& s)
+{
static std::map<std::string, opcodetype> mapOpNames;
if (mapOpNames.empty())
@@ -40,11 +39,23 @@ CScript ParseScript(const std::string& s)
continue;
mapOpNames[strName] = static_cast<opcodetype>(op);
// Convenience: OP_ADD and just ADD are both recognized:
- boost::algorithm::replace_first(strName, "OP_", "");
- mapOpNames[strName] = static_cast<opcodetype>(op);
+ if (strName.compare(0, 3, "OP_") == 0) { // strName starts with "OP_"
+ mapOpNames[strName.substr(3)] = static_cast<opcodetype>(op);
+ }
}
}
+ auto it = mapOpNames.find(s);
+ if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode");
+ return it->second;
+}
+
+} // namespace
+
+CScript ParseScript(const std::string& s)
+{
+ CScript result;
+
std::vector<std::string> words;
boost::algorithm::split(words, s, boost::algorithm::is_any_of(" \t\n"), boost::algorithm::token_compress_on);
@@ -82,14 +93,10 @@ CScript ParseScript(const std::string& s)
std::vector<unsigned char> value(w->begin()+1, w->end()-1);
result << value;
}
- else if (mapOpNames.count(*w))
- {
- // opcode, e.g. OP_ADD or ADD:
- result << mapOpNames[*w];
- }
else
{
- throw std::runtime_error("script parse error");
+ // opcode, e.g. OP_ADD or ADD:
+ result << ParseOpCode(*w);
}
}
@@ -119,31 +126,72 @@ static bool CheckTxScriptsSanity(const CMutableTransaction& tx)
static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data, bool try_no_witness, bool try_witness)
{
+ // General strategy:
+ // - Decode both with extended serialization (which interprets the 0x0001 tag as a marker for
+ // the presense of witnesses) and with legacy serialization (which interprets the tag as a
+ // 0-input 1-output incomplete transaction).
+ // - Restricted by try_no_witness (which disables legacy if false) and try_witness (which
+ // disables extended if false).
+ // - Ignore serializations that do not fully consume the hex string.
+ // - If neither succeeds, fail.
+ // - If only one succeeds, return that one.
+ // - If both decode attempts succeed:
+ // - If only one passes the CheckTxScriptsSanity check, return that one.
+ // - If neither or both pass CheckTxScriptsSanity, return the extended one.
+
+ CMutableTransaction tx_extended, tx_legacy;
+ bool ok_extended = false, ok_legacy = false;
+
+ // Try decoding with extended serialization support, and remember if the result successfully
+ // consumes the entire input.
if (try_witness) {
CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION);
try {
- ssData >> tx;
- // If transaction looks sane, we don't try other mode even if requested
- if (ssData.empty() && (!try_no_witness || CheckTxScriptsSanity(tx))) {
- return true;
- }
+ ssData >> tx_extended;
+ if (ssData.empty()) ok_extended = true;
} catch (const std::exception&) {
// Fall through.
}
}
+ // Optimization: if extended decoding succeeded and the result passes CheckTxScriptsSanity,
+ // don't bother decoding the other way.
+ if (ok_extended && CheckTxScriptsSanity(tx_extended)) {
+ tx = std::move(tx_extended);
+ return true;
+ }
+
+ // Try decoding with legacy serialization, and remember if the result successfully consumes the entire input.
if (try_no_witness) {
CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
try {
- ssData >> tx;
- if (ssData.empty()) {
- return true;
- }
+ ssData >> tx_legacy;
+ if (ssData.empty()) ok_legacy = true;
} catch (const std::exception&) {
// Fall through.
}
}
+ // If legacy decoding succeeded and passes CheckTxScriptsSanity, that's our answer, as we know
+ // at this point that extended decoding either failed or doesn't pass the sanity check.
+ if (ok_legacy && CheckTxScriptsSanity(tx_legacy)) {
+ tx = std::move(tx_legacy);
+ return true;
+ }
+
+ // If extended decoding succeeded, and neither decoding passes sanity, return the extended one.
+ if (ok_extended) {
+ tx = std::move(tx_extended);
+ return true;
+ }
+
+ // If legacy decoding succeeded and extended didn't, return the legacy one.
+ if (ok_legacy) {
+ tx = std::move(tx_legacy);
+ return true;
+ }
+
+ // If none succeeded, we failed.
return false;
}
diff --git a/src/crc32c/.appveyor.yml b/src/crc32c/.appveyor.yml
index 7345746750..b23e02e88a 100644
--- a/src/crc32c/.appveyor.yml
+++ b/src/crc32c/.appveyor.yml
@@ -8,9 +8,9 @@ environment:
matrix:
# AppVeyor currently has no custom job name feature.
# http://help.appveyor.com/discussions/questions/1623-can-i-provide-a-friendly-name-for-jobs
- - JOB: Visual Studio 2017
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- CMAKE_GENERATOR: Visual Studio 15 2017
+ - JOB: Visual Studio 2019
+ APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+ CMAKE_GENERATOR: Visual Studio 16 2019
platform:
- x86
@@ -24,10 +24,11 @@ build_script:
- git submodule update --init --recursive
- mkdir build
- cd build
- - if "%platform%"=="x64" set CMAKE_GENERATOR=%CMAKE_GENERATOR% Win64
+ - if "%platform%"=="x86" (set CMAKE_GENERATOR_PLATFORM="Win32")
+ else (set CMAKE_GENERATOR_PLATFORM="%platform%")
- cmake --version
- - cmake .. -G "%CMAKE_GENERATOR%" -DCRC32C_USE_GLOG=0
- -DCMAKE_CONFIGURATION_TYPES="%CONFIGURATION%"
+ - cmake .. -G "%CMAKE_GENERATOR%" -A "%CMAKE_GENERATOR_PLATFORM%"
+ -DCMAKE_CONFIGURATION_TYPES="%CONFIGURATION%" -DCRC32C_USE_GLOG=0
- cmake --build . --config "%CONFIGURATION%"
- cd ..
diff --git a/src/crc32c/AUTHORS b/src/crc32c/AUTHORS
index 6f1f6871a6..ef9b4ea933 100644
--- a/src/crc32c/AUTHORS
+++ b/src/crc32c/AUTHORS
@@ -7,3 +7,5 @@ Google Inc.
Fangming Fang <Fangming.Fang@arm.com>
Vadim Skipin <vadim.skipin@gmail.com>
+Rodrigo Tobar <rtobar@icrar.org>
+Harry Mallon <hjmallon@gmail.com>
diff --git a/src/crc32c/CMakeLists.txt b/src/crc32c/CMakeLists.txt
index 111a3e3614..71692d5796 100644
--- a/src/crc32c/CMakeLists.txt
+++ b/src/crc32c/CMakeLists.txt
@@ -5,15 +5,21 @@
cmake_minimum_required(VERSION 3.1)
project(Crc32c VERSION 1.1.0 LANGUAGES C CXX)
-# This project can use C11, but will gracefully decay down to C89.
-set(CMAKE_C_STANDARD 11)
-set(CMAKE_C_STANDARD_REQUIRED OFF)
-set(CMAKE_C_EXTENSIONS OFF)
-
-# This project requires C++11.
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
+# C standard can be overridden when this is used as a sub-project.
+if(NOT CMAKE_C_STANDARD)
+ # This project can use C11, but will gracefully decay down to C89.
+ set(CMAKE_C_STANDARD 11)
+ set(CMAKE_C_STANDARD_REQUIRED OFF)
+ set(CMAKE_C_EXTENSIONS OFF)
+endif(NOT CMAKE_C_STANDARD)
+
+# C++ standard can be overridden when this is used as a sub-project.
+if(NOT CMAKE_CXX_STANDARD)
+ # This project requires C++11.
+ set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ set(CMAKE_CXX_EXTENSIONS OFF)
+endif(NOT CMAKE_CXX_STANDARD)
# https://github.com/izenecloud/cmake/blob/master/SetCompilerWarningAll.cmake
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
@@ -269,7 +275,7 @@ target_sources(crc32c
PRIVATE
"${PROJECT_BINARY_DIR}/include/crc32c/crc32c_config.h"
"src/crc32c_arm64.h"
- "src/crc32c_arm64_linux_check.h"
+ "src/crc32c_arm64_check.h"
"src/crc32c_internal.h"
"src/crc32c_portable.cc"
"src/crc32c_prefetch.h"
@@ -405,19 +411,24 @@ if(CRC32C_INSTALL)
)
include(CMakePackageConfigHelpers)
+ configure_package_config_file(
+ "${PROJECT_NAME}Config.cmake.in"
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
+ )
write_basic_package_version_file(
- "${PROJECT_BINARY_DIR}/Crc32cConfigVersion.cmake"
- COMPATIBILITY SameMajorVersion
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
+ COMPATIBILITY SameMajorVersion
)
install(
EXPORT Crc32cTargets
NAMESPACE Crc32c::
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Crc32c"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
install(
FILES
- "Crc32cConfig.cmake"
- "${PROJECT_BINARY_DIR}/Crc32cConfigVersion.cmake"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Crc32c"
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
+ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
)
endif(CRC32C_INSTALL)
diff --git a/src/crc32c/Crc32cConfig.cmake b/src/crc32c/Crc32cConfig.cmake.in
index 4d6057ec26..c6b8fc7913 100644
--- a/src/crc32c/Crc32cConfig.cmake
+++ b/src/crc32c/Crc32cConfig.cmake.in
@@ -2,4 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. See the AUTHORS file for names of contributors.
+@PACKAGE_INIT@
+
include("${CMAKE_CURRENT_LIST_DIR}/Crc32cTargets.cmake")
+
+check_required_components(Crc32c)
diff --git a/src/crc32c/src/crc32c.cc b/src/crc32c/src/crc32c.cc
index 4d3018af47..804133bc17 100644
--- a/src/crc32c/src/crc32c.cc
+++ b/src/crc32c/src/crc32c.cc
@@ -8,7 +8,7 @@
#include <cstdint>
#include "./crc32c_arm64.h"
-#include "./crc32c_arm64_linux_check.h"
+#include "./crc32c_arm64_check.h"
#include "./crc32c_internal.h"
#include "./crc32c_sse42.h"
#include "./crc32c_sse42_check.h"
@@ -20,8 +20,8 @@ uint32_t Extend(uint32_t crc, const uint8_t* data, size_t count) {
static bool can_use_sse42 = CanUseSse42();
if (can_use_sse42) return ExtendSse42(crc, data, count);
#elif HAVE_ARM64_CRC32C
- static bool can_use_arm_linux = CanUseArm64Linux();
- if (can_use_arm_linux) return ExtendArm64(crc, data, count);
+ static bool can_use_arm64_crc32 = CanUseArm64Crc32();
+ if (can_use_arm64_crc32) return ExtendArm64(crc, data, count);
#endif // HAVE_SSE42 && (defined(_M_X64) || defined(__x86_64__))
return ExtendPortable(crc, data, count);
diff --git a/src/crc32c/src/crc32c_arm64.cc b/src/crc32c/src/crc32c_arm64.cc
index b872245f95..1da04ed34a 100644
--- a/src/crc32c/src/crc32c_arm64.cc
+++ b/src/crc32c/src/crc32c_arm64.cc
@@ -64,7 +64,7 @@
namespace crc32c {
-uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
+uint32_t ExtendArm64(uint32_t crc, const uint8_t *data, size_t size) {
int64_t length = size;
uint32_t crc0, crc1, crc2, crc3;
uint64_t t0, t1, t2;
@@ -74,7 +74,6 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
const poly64_t k0 = 0x8d96551c, k1 = 0xbd6f81f8, k2 = 0xdcb17aa4;
crc = crc ^ kCRC32Xor;
- const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
while (length >= KBYTES) {
crc0 = crc;
@@ -83,14 +82,14 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
crc3 = 0;
// Process 1024 bytes in parallel.
- CRC32C1024BYTES(p);
+ CRC32C1024BYTES(data);
// Merge the 4 partial CRC32C values.
t2 = (uint64_t)vmull_p64(crc2, k2);
t1 = (uint64_t)vmull_p64(crc1, k1);
t0 = (uint64_t)vmull_p64(crc0, k0);
- crc = __crc32cd(crc3, *(uint64_t *)p);
- p += sizeof(uint64_t);
+ crc = __crc32cd(crc3, *(uint64_t *)data);
+ data += sizeof(uint64_t);
crc ^= __crc32cd(0, t2);
crc ^= __crc32cd(0, t1);
crc ^= __crc32cd(0, t0);
@@ -99,23 +98,23 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *buf, size_t size) {
}
while (length >= 8) {
- crc = __crc32cd(crc, *(uint64_t *)p);
- p += 8;
+ crc = __crc32cd(crc, *(uint64_t *)data);
+ data += 8;
length -= 8;
}
if (length & 4) {
- crc = __crc32cw(crc, *(uint32_t *)p);
- p += 4;
+ crc = __crc32cw(crc, *(uint32_t *)data);
+ data += 4;
}
if (length & 2) {
- crc = __crc32ch(crc, *(uint16_t *)p);
- p += 2;
+ crc = __crc32ch(crc, *(uint16_t *)data);
+ data += 2;
}
if (length & 1) {
- crc = __crc32cb(crc, *p);
+ crc = __crc32cb(crc, *data);
}
return crc ^ kCRC32Xor;
diff --git a/src/crc32c/src/crc32c_arm64.h b/src/crc32c/src/crc32c_arm64.h
index 100cd56ec8..e093687ddc 100644
--- a/src/crc32c/src/crc32c_arm64.h
+++ b/src/crc32c/src/crc32c_arm64.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
-// Linux-specific code checking the availability for ARM CRC32C instructions.
+// ARM-specific code
-#ifndef CRC32C_CRC32C_ARM_LINUX_H_
-#define CRC32C_CRC32C_ARM_LINUX_H_
+#ifndef CRC32C_CRC32C_ARM_H_
+#define CRC32C_CRC32C_ARM_H_
#include <cstddef>
#include <cstdint>
@@ -24,4 +24,4 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t* data, size_t count);
#endif // HAVE_ARM64_CRC32C
-#endif // CRC32C_CRC32C_ARM_LINUX_H_
+#endif // CRC32C_CRC32C_ARM_H_
diff --git a/src/crc32c/src/crc32c_arm64_linux_check.h b/src/crc32c/src/crc32c_arm64_check.h
index 1a20a757bb..62a07aba09 100644
--- a/src/crc32c/src/crc32c_arm64_linux_check.h
+++ b/src/crc32c/src/crc32c_arm64_check.h
@@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
-// ARM Linux-specific code checking for the availability of CRC32C instructions.
+// ARM-specific code checking for the availability of CRC32C instructions.
-#ifndef CRC32C_CRC32C_ARM_LINUX_CHECK_H_
-#define CRC32C_CRC32C_ARM_LINUX_CHECK_H_
-
-// X86-specific code checking for the availability of SSE4.2 instructions.
+#ifndef CRC32C_CRC32C_ARM_CHECK_H_
+#define CRC32C_CRC32C_ARM_CHECK_H_
#include <cstddef>
#include <cstdint>
@@ -18,6 +16,7 @@
#if HAVE_ARM64_CRC32C
+#ifdef __linux__
#if HAVE_STRONG_GETAUXVAL
#include <sys/auxv.h>
#elif HAVE_WEAK_GETAUXVAL
@@ -27,17 +26,28 @@ extern "C" unsigned long getauxval(unsigned long type) __attribute__((weak));
#define AT_HWCAP 16
#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
+#endif // defined (__linux__)
+
+#ifdef __APPLE__
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif // defined (__APPLE__)
namespace crc32c {
-inline bool CanUseArm64Linux() {
-#if HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
+inline bool CanUseArm64Crc32() {
+#if defined (__linux__) && (HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL)
// From 'arch/arm64/include/uapi/asm/hwcap.h' in Linux kernel source code.
constexpr unsigned long kHWCAP_PMULL = 1 << 4;
constexpr unsigned long kHWCAP_CRC32 = 1 << 7;
unsigned long hwcap = (&getauxval != nullptr) ? getauxval(AT_HWCAP) : 0;
return (hwcap & (kHWCAP_PMULL | kHWCAP_CRC32)) ==
(kHWCAP_PMULL | kHWCAP_CRC32);
+#elif defined(__APPLE__)
+ int val = 0;
+ size_t len = sizeof(val);
+ return sysctlbyname("hw.optional.armv8_crc32", &val, &len, nullptr, 0) == 0
+ && val != 0;
#else
return false;
#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
@@ -47,4 +57,4 @@ inline bool CanUseArm64Linux() {
#endif // HAVE_ARM64_CRC32C
-#endif // CRC32C_CRC32C_ARM_LINUX_CHECK_H_
+#endif // CRC32C_CRC32C_ARM_CHECK_H_
diff --git a/src/crc32c/src/crc32c_benchmark.cc b/src/crc32c/src/crc32c_benchmark.cc
index c464304b3f..51194b370a 100644
--- a/src/crc32c/src/crc32c_benchmark.cc
+++ b/src/crc32c/src/crc32c_benchmark.cc
@@ -16,7 +16,7 @@
#endif // CRC32C_TESTS_BUILT_WITH_GLOG
#include "./crc32c_arm64.h"
-#include "./crc32c_arm64_linux_check.h"
+#include "./crc32c_arm64_check.h"
#include "./crc32c_internal.h"
#include "./crc32c_sse42.h"
#include "./crc32c_sse42_check.h"
@@ -58,8 +58,8 @@ BENCHMARK_REGISTER_F(CRC32CBenchmark, Portable)
#if HAVE_ARM64_CRC32C
-BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmLinux)(benchmark::State& state) {
- if (!crc32c::CanUseArm64Linux()) {
+BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmCRC32C)(benchmark::State& state) {
+ if (!crc32c::CanUseArm64Crc32()) {
state.SkipWithError("ARM CRC32C instructions not available or not enabled");
return;
}
@@ -69,7 +69,7 @@ BENCHMARK_DEFINE_F(CRC32CBenchmark, ArmLinux)(benchmark::State& state) {
crc = crc32c::ExtendArm64(crc, block_buffer_, block_size_);
state.SetBytesProcessed(state.iterations() * block_size_);
}
-BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmLinux)
+BENCHMARK_REGISTER_F(CRC32CBenchmark, ArmCRC32C)
->RangeMultiplier(16)
->Range(256, 16777216); // Block size.
diff --git a/src/crc32c/src/crc32c_read_le.h b/src/crc32c/src/crc32c_read_le.h
index 3bd45fe3aa..673a2a0db7 100644
--- a/src/crc32c/src/crc32c_read_le.h
+++ b/src/crc32c/src/crc32c_read_le.h
@@ -32,14 +32,14 @@ inline uint32_t ReadUint32LE(const uint8_t* buffer) {
// Reads a little-endian 64-bit integer from a 64-bit-aligned buffer.
inline uint64_t ReadUint64LE(const uint8_t* buffer) {
#if BYTE_ORDER_BIG_ENDIAN
- return ((static_cast<uint32_t>(static_cast<uint8_t>(buffer[0]))) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[1])) << 8) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[2])) << 16) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[3])) << 24) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[4])) << 32) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[5])) << 40) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[6])) << 48) |
- (static_cast<uint32_t>(static_cast<uint8_t>(buffer[7])) << 56));
+ return ((static_cast<uint64_t>(static_cast<uint8_t>(buffer[0]))) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[1])) << 8) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[2])) << 16) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[3])) << 24) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[4])) << 32) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[5])) << 40) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[6])) << 48) |
+ (static_cast<uint64_t>(static_cast<uint8_t>(buffer[7])) << 56));
#else // !BYTE_ORDER_BIG_ENDIAN
uint64_t result;
// This should be optimized to a single instruction.
diff --git a/src/dummywallet.cpp b/src/dummywallet.cpp
index 8d2dcd0279..4543f098a1 100644
--- a/src/dummywallet.cpp
+++ b/src/dummywallet.cpp
@@ -40,7 +40,6 @@ void DummyWalletInit::AddWalletOptions(ArgsManager& argsman) const
"-salvagewallet",
"-spendzeroconfchange",
"-txconfirmtarget=<n>",
- "-upgradewallet",
"-wallet=<path>",
"-walletbroadcast",
"-walletdir=<dir>",
diff --git a/src/hash.h b/src/hash.h
index 6d876076ee..083ac12523 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -197,7 +197,7 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
}
/** Single-SHA256 a 32-byte input (represented as uint256). */
-NODISCARD uint256 SHA256Uint256(const uint256& input);
+[[nodiscard]] uint256 SHA256Uint256(const uint256& input);
unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vDataToHash);
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index f1b9997371..cb8b220895 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -68,6 +68,8 @@ private:
static std::string strRPCUserColonPass;
/* Stored RPC timer interface (for unregistration) */
static std::unique_ptr<HTTPRPCTimerInterface> httpRPCTimerInterface;
+/* List of -rpcauth values */
+static std::vector<std::vector<std::string>> g_rpcauth;
/* RPC Auth Whitelist */
static std::map<std::string, std::set<std::string>> g_rpc_whitelist;
static bool g_rpc_whitelist_default = false;
@@ -99,15 +101,7 @@ static bool multiUserAuthorized(std::string strUserPass)
std::string strUser = strUserPass.substr(0, strUserPass.find(':'));
std::string strPass = strUserPass.substr(strUserPass.find(':') + 1);
- for (const std::string& strRPCAuth : gArgs.GetArgs("-rpcauth")) {
- //Search for multi-user login/pass "rpcauth" from config
- std::vector<std::string> vFields;
- boost::split(vFields, strRPCAuth, boost::is_any_of(":$"));
- if (vFields.size() != 3) {
- //Incorrect formatting in config file
- continue;
- }
-
+ for (const auto& vFields : g_rpcauth) {
std::string strName = vFields[0];
if (!TimingResistantEqual(strName, strUser)) {
continue;
@@ -259,6 +253,16 @@ static bool InitRPCAuthentication()
if (gArgs.GetArg("-rpcauth","") != "")
{
LogPrintf("Using rpcauth authentication.\n");
+ for (const std::string& rpcauth : gArgs.GetArgs("-rpcauth")) {
+ std::vector<std::string> fields;
+ boost::split(fields, rpcauth, boost::is_any_of(":$"));
+ if (fields.size() == 3) {
+ g_rpcauth.push_back(fields);
+ } else {
+ LogPrintf("Invalid -rpcauth argument.\n");
+ return false;
+ }
+ }
}
g_rpc_whitelist_default = gArgs.GetBoolArg("-rpcwhitelistdefault", gArgs.IsArgSet("-rpcwhitelist"));
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 1e5ea2de83..0a8e58ab67 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -33,13 +33,6 @@
#include <support/events.h>
-#ifdef EVENT__HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#ifdef _XOPEN_SOURCE_EXTENDED
-#include <arpa/inet.h>
-#endif
-#endif
-
/** Maximum size of http request (request line + headers) */
static const size_t MAX_HEADERS_SIZE = 8192;
diff --git a/src/init.cpp b/src/init.cpp
index 1387d6b982..46dce6aa97 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -85,7 +85,6 @@
#include <zmq/zmqrpc.h>
#endif
-static bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
@@ -99,8 +98,6 @@ static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
#define MIN_CORE_FILEDESCRIPTORS 150
#endif
-static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
-
static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";
/**
@@ -113,7 +110,7 @@ static fs::path GetPidFile(const ArgsManager& args)
return AbsPathForConfigVal(fs::path(args.GetArg("-pid", BITCOIN_PID_FILENAME)));
}
-NODISCARD static bool CreatePidFile(const ArgsManager& args)
+[[nodiscard]] static bool CreatePidFile(const ArgsManager& args)
{
fsbridge::ofstream file{GetPidFile(args)};
if (file) {
@@ -203,7 +200,7 @@ void Shutdown(NodeContext& node)
// using the other before destroying them.
if (node.peerman) UnregisterValidationInterface(node.peerman.get());
// Follow the lock order requirements:
- // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount
+ // * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraFullOutboundCount
// which locks cs_vNodes.
// * ProcessMessage locks cs_main and g_cs_orphans before indirectly calling ForEachNode which
// locks cs_vNodes.
@@ -236,17 +233,8 @@ void Shutdown(NodeContext& node)
DumpMempool(*node.mempool);
}
- if (fFeeEstimatesInitialized)
- {
- ::feeEstimator.FlushUnconfirmed();
- fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION);
- if (!est_fileout.IsNull())
- ::feeEstimator.Write(est_fileout);
- else
- LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
- fFeeEstimatesInitialized = false;
- }
+ // Drop transactions we were still watching, and record fee estimations.
+ if (node.fee_estimator) node.fee_estimator->Flush();
// FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
if (node.chainman) {
@@ -304,6 +292,7 @@ void Shutdown(NodeContext& node)
globalVerifyHandle.reset();
ECC_Stop();
node.mempool.reset();
+ node.fee_estimator.reset();
node.chainman = nullptr;
node.scheduler.reset();
@@ -914,7 +903,7 @@ std::set<BlockFilterType> g_enabled_filter_types;
std::terminate();
};
-bool AppInitBasicSetup(ArgsManager& args)
+bool AppInitBasicSetup(const ArgsManager& args)
{
// ********************************************************* Step 1: setup
#ifdef _MSC_VER
@@ -928,6 +917,9 @@ bool AppInitBasicSetup(ArgsManager& args)
// Enable heap terminate-on-corruption
HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
#endif
+ if (!InitShutdownState()) {
+ return InitError(Untranslated("Initializing wait-for-shutdown state failed."));
+ }
if (!SetupNetworking()) {
return InitError(Untranslated("Initializing networking failed."));
@@ -1039,7 +1031,7 @@ bool AppInitParameterInteraction(const ArgsManager& args)
// Trim requested connection counts, to fit into system limitations
// <int> in std::min<int>(...) to work around FreeBSD compilation issue described in #2695
- nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS);
+ nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS + nBind);
#ifdef USE_POLL
int fd_max = nFD;
#else
@@ -1145,7 +1137,7 @@ bool AppInitParameterInteraction(const ArgsManager& args)
if (!ParseMoney(args.GetArg("-minrelaytxfee", ""), n)) {
return InitError(AmountErrMsg("minrelaytxfee", args.GetArg("-minrelaytxfee", "")));
}
- // High fee check is done afterward in CWallet::CreateWalletFromFile()
+ // High fee check is done afterward in CWallet::Create()
::minRelayTxFee = CFeeRate(n);
} else if (incrementalRelayFee > ::minRelayTxFee) {
// Allow only setting incrementalRelayFee to control both
@@ -1384,27 +1376,31 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
// is not yet setup and may end up being set up twice if we
// need to reindex later.
+ fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
+ fDiscover = args.GetBoolArg("-discover", true);
+ const bool ignores_incoming_txs{args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)};
+
assert(!node.banman);
node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
assert(!node.connman);
node.connman = MakeUnique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()), args.GetBoolArg("-networkactive", true));
- // Make mempool generally available in the node context. For example the connection manager, wallet, or RPC threads,
- // which are all started after this, may use it from the node context.
+ 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>();
+
assert(!node.mempool);
- node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator);
- if (node.mempool) {
- int ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
- if (ratio != 0) {
- node.mempool->setSanityCheck(1.0 / ratio);
- }
- }
+ int check_ratio = std::min<int>(std::max<int>(args.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
+ node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get(), check_ratio);
assert(!node.chainman);
node.chainman = &g_chainman;
ChainstateManager& chainman = *Assert(node.chainman);
- node.peerman.reset(new PeerManager(chainparams, *node.connman, node.banman.get(), *node.scheduler, chainman, *node.mempool));
+ assert(!node.peerman);
+ node.peerman = std::make_unique<PeerManager>(chainparams, *node.connman, node.banman.get(),
+ *node.scheduler, chainman, *node.mempool, ignores_incoming_txs);
RegisterValidationInterface(node.peerman.get());
// sanitize comments per BIP-0014, format user agent and check total size
@@ -1480,11 +1476,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
}
}
- // see Step 2: parameter interactions for more information about these
- fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
- fDiscover = args.GetBoolArg("-discover", true);
- g_relay_txes = !args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
-
for (const std::string& strAddr : args.GetArgs("-externalip")) {
CService addrLocal;
if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
@@ -1525,12 +1516,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
RegisterValidationInterface(g_zmq_notification_interface);
}
#endif
- uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set
- uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME;
-
- if (args.IsArgSet("-maxuploadtarget")) {
- nMaxOutboundLimit = args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET) * 1024 * 1024;
- }
// ********************************************************* Step 7: load block chain
@@ -1792,13 +1777,6 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
return false;
}
- fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
- // Allowed to fail as this file IS missing on first startup.
- if (!est_filein.IsNull())
- ::feeEstimator.Read(est_filein);
- fFeeEstimatesInitialized = true;
-
// ********************************************************* Step 8: start indexers
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
g_txindex = MakeUnique<TxIndex>(nTxIndexCache, false, fReindex);
@@ -1940,8 +1918,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
connOptions.nReceiveFloodSize = 1000 * args.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
connOptions.m_added_nodes = args.GetArgs("-addnode");
- connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe;
- connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
+ connOptions.nMaxOutboundLimit = 1024 * 1024 * args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET);
connOptions.m_peer_connect_timeout = peer_connect_timeout;
for (const std::string& bind_arg : args.GetArgs("-bind")) {
diff --git a/src/init.h b/src/init.h
index 679e875da1..c04d966d06 100644
--- a/src/init.h
+++ b/src/init.h
@@ -33,7 +33,7 @@ void InitParameterInteraction(ArgsManager& args);
* @note This can be done before daemonization. Do not call Shutdown() if this function fails.
* @pre Parameters should be parsed and config file should be read.
*/
-bool AppInitBasicSetup(ArgsManager& args);
+bool AppInitBasicSetup(const ArgsManager& args);
/**
* Initialization: parameter interaction.
* @note This can be done before daemonization. Do not call Shutdown() if this function fails.
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 85d09be0f3..1a49518d69 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -44,6 +44,10 @@ public:
FoundBlock& time(int64_t& time) { m_time = &time; return *this; }
FoundBlock& maxTime(int64_t& max_time) { m_max_time = &max_time; return *this; }
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 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
//! (for example due to pruning), the CBlock variable will be set to null.
FoundBlock& data(CBlock& data) { m_data = &data; return *this; }
@@ -53,6 +57,8 @@ public:
int64_t* m_time = nullptr;
int64_t* m_max_time = nullptr;
int64_t* m_mtp_time = nullptr;
+ bool* m_in_active_chain = nullptr;
+ const FoundBlock* m_next_block = nullptr;
CBlock* m_data = nullptr;
};
@@ -77,9 +83,9 @@ public:
//! wallet cache it, fee estimation being driven by node mempool, wallet
//! should be the consumer.
//!
-//! * The `guessVerificationProgress`, `getBlockHeight`, `getBlockHash`, etc
-//! methods can go away if rescan logic is moved on the node side, and wallet
-//! only register rescan request.
+//! * `guessVerificationProgress` and similar methods can go away if rescan
+//! logic moves out of the wallet, and the wallet just requests scans from the
+//! node (https://github.com/bitcoin/bitcoin/issues/11756)
class Chain
{
public:
@@ -90,11 +96,6 @@ public:
//! any blocks)
virtual Optional<int> getHeight() = 0;
- //! Get block height above genesis block. Returns 0 for genesis block,
- //! 1 for following block, and so on. Returns nullopt for a block not
- //! included in the current chain.
- virtual Optional<int> getBlockHeight(const uint256& hash) = 0;
-
//! Get block hash. Height must be valid or this function will abort.
virtual uint256 getBlockHash(int height) = 0;
@@ -102,13 +103,6 @@ public:
//! pruned), and contains transactions.
virtual bool haveBlockOnDisk(int height) = 0;
- //! Return height of the first block in the chain with timestamp equal
- //! or greater than the given time and height equal or greater than the
- //! given height, or nullopt if there is no block with a high enough
- //! timestamp and height. Also return the block hash as an optional output parameter
- //! (to avoid the cost of a second lookup in case this information is needed.)
- virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0;
-
//! Get locator for the current chain tip.
virtual CBlockLocator getTipLocator() = 0;
@@ -130,11 +124,6 @@ public:
//! information.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block={}) = 0;
- //! Find next block if block is part of current chain. Also flag if
- //! there was a reorg and the specified block hash is no longer in the
- //! current chain, and optionally return block information.
- virtual bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next={}, bool* reorg=nullptr) = 0;
-
//! Find ancestor of block at specified height and optionally return
//! ancestor information.
virtual bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out={}) = 0;
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
deleted file mode 100644
index 2c5f8627e6..0000000000
--- a/src/interfaces/node.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright (c) 2018-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.
-
-#include <interfaces/node.h>
-
-#include <addrdb.h>
-#include <banman.h>
-#include <chain.h>
-#include <chainparams.h>
-#include <init.h>
-#include <interfaces/chain.h>
-#include <interfaces/handler.h>
-#include <interfaces/wallet.h>
-#include <net.h>
-#include <net_processing.h>
-#include <netaddress.h>
-#include <netbase.h>
-#include <node/context.h>
-#include <node/ui_interface.h>
-#include <policy/feerate.h>
-#include <policy/fees.h>
-#include <policy/settings.h>
-#include <primitives/block.h>
-#include <rpc/server.h>
-#include <shutdown.h>
-#include <support/allocators/secure.h>
-#include <sync.h>
-#include <txmempool.h>
-#include <util/check.h>
-#include <util/ref.h>
-#include <util/system.h>
-#include <util/translation.h>
-#include <validation.h>
-#include <warnings.h>
-
-#if defined(HAVE_CONFIG_H)
-#include <config/bitcoin-config.h>
-#endif
-
-#include <univalue.h>
-
-#include <boost/signals2/signal.hpp>
-
-namespace interfaces {
-namespace {
-
-class NodeImpl : public Node
-{
-public:
- NodeImpl(NodeContext* context) { setContext(context); }
- void initLogging() override { InitLogging(*Assert(m_context->args)); }
- void initParameterInteraction() override { InitParameterInteraction(*Assert(m_context->args)); }
- bilingual_str getWarnings() override { return GetWarnings(true); }
- uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); }
- bool baseInitialize() override
- {
- return AppInitBasicSetup(gArgs) && AppInitParameterInteraction(gArgs) && AppInitSanityChecks() &&
- AppInitLockDataDirectory() && AppInitInterfaces(*m_context);
- }
- bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override
- {
- return AppInitMain(m_context_ref, *m_context, tip_info);
- }
- void appShutdown() override
- {
- Interrupt(*m_context);
- Shutdown(*m_context);
- }
- void startShutdown() override
- {
- StartShutdown();
- // Stop RPC for clean shutdown if any of waitfor* commands is executed.
- if (gArgs.GetBoolArg("-server", false)) {
- InterruptRPC();
- StopRPC();
- }
- }
- bool shutdownRequested() override { return ShutdownRequested(); }
- void mapPort(bool use_upnp) override
- {
- if (use_upnp) {
- StartMapPort();
- } else {
- InterruptMapPort();
- StopMapPort();
- }
- }
- bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); }
- size_t getNodeCount(CConnman::NumConnections flags) override
- {
- return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0;
- }
- bool getNodesStats(NodesStats& stats) override
- {
- stats.clear();
-
- if (m_context->connman) {
- std::vector<CNodeStats> stats_temp;
- m_context->connman->GetNodeStats(stats_temp);
-
- stats.reserve(stats_temp.size());
- for (auto& node_stats_temp : stats_temp) {
- stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats());
- }
-
- // Try to retrieve the CNodeStateStats for each node.
- TRY_LOCK(::cs_main, lockMain);
- if (lockMain) {
- for (auto& node_stats : stats) {
- std::get<1>(node_stats) =
- GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
- }
- }
- return true;
- }
- return false;
- }
- bool getBanned(banmap_t& banmap) override
- {
- if (m_context->banman) {
- m_context->banman->GetBanned(banmap);
- return true;
- }
- return false;
- }
- bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override
- {
- if (m_context->banman) {
- m_context->banman->Ban(net_addr, ban_time_offset);
- return true;
- }
- return false;
- }
- bool unban(const CSubNet& ip) override
- {
- if (m_context->banman) {
- m_context->banman->Unban(ip);
- return true;
- }
- return false;
- }
- bool disconnectByAddress(const CNetAddr& net_addr) override
- {
- if (m_context->connman) {
- return m_context->connman->DisconnectNode(net_addr);
- }
- return false;
- }
- bool disconnectById(NodeId id) override
- {
- if (m_context->connman) {
- return m_context->connman->DisconnectNode(id);
- }
- return false;
- }
- int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; }
- int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; }
- size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; }
- size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; }
- bool getHeaderTip(int& height, int64_t& block_time) override
- {
- LOCK(::cs_main);
- if (::pindexBestHeader) {
- height = ::pindexBestHeader->nHeight;
- block_time = ::pindexBestHeader->GetBlockTime();
- return true;
- }
- return false;
- }
- int getNumBlocks() override
- {
- LOCK(::cs_main);
- return ::ChainActive().Height();
- }
- uint256 getBestBlockHash() override
- {
- const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip());
- return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
- }
- int64_t getLastBlockTime() override
- {
- LOCK(::cs_main);
- if (::ChainActive().Tip()) {
- return ::ChainActive().Tip()->GetBlockTime();
- }
- return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
- }
- double getVerificationProgress() override
- {
- const CBlockIndex* tip;
- {
- LOCK(::cs_main);
- tip = ::ChainActive().Tip();
- }
- return GuessVerificationProgress(Params().TxData(), tip);
- }
- bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
- bool getReindex() override { return ::fReindex; }
- bool getImporting() override { return ::fImporting; }
- void setNetworkActive(bool active) override
- {
- if (m_context->connman) {
- m_context->connman->SetNetworkActive(active);
- }
- }
- bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
- CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) override
- {
- FeeCalculation fee_calc;
- CFeeRate result = ::feeEstimator.estimateSmartFee(num_blocks, &fee_calc, conservative);
- if (returned_target) {
- *returned_target = fee_calc.returnedTarget;
- }
- return result;
- }
- CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
- UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
- {
- JSONRPCRequest req(m_context_ref);
- req.params = params;
- req.strMethod = command;
- req.URI = uri;
- return ::tableRPC.execute(req);
- }
- std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); }
- void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); }
- void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); }
- bool getUnspentOutput(const COutPoint& output, Coin& coin) override
- {
- LOCK(::cs_main);
- return ::ChainstateActive().CoinsTip().GetCoin(output, coin);
- }
- WalletClient& walletClient() override
- {
- return *Assert(m_context->wallet_client);
- }
- std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
- {
- return MakeHandler(::uiInterface.InitMessage_connect(fn));
- }
- std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override
- {
- return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn));
- }
- std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override
- {
- return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn));
- }
- std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
- {
- return MakeHandler(::uiInterface.ShowProgress_connect(fn));
- }
- std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
- {
- return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));
- }
- std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override
- {
- return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn));
- }
- std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override
- {
- return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn));
- }
- std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override
- {
- return MakeHandler(::uiInterface.BannedListChanged_connect(fn));
- }
- std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
- {
- return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
- fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
- GuessVerificationProgress(Params().TxData(), block));
- }));
- }
- 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);
- }));
- }
- NodeContext* context() override { return m_context; }
- void setContext(NodeContext* context) override
- {
- m_context = context;
- if (context) {
- m_context_ref.Set(*context);
- } else {
- m_context_ref.Clear();
- }
- }
- NodeContext* m_context{nullptr};
- util::Ref m_context_ref;
-};
-
-} // namespace
-
-std::unique_ptr<Node> MakeNode(NodeContext* context) { return MakeUnique<NodeImpl>(context); }
-
-} // namespace interfaces
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 5079be038e..36f76aeb4f 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -151,9 +151,6 @@ public:
//! Get network active.
virtual bool getNetworkActive() = 0;
- //! Estimate smart fee.
- virtual CFeeRate estimateSmartFee(int num_blocks, bool conservative, int* returned_target = nullptr) = 0;
-
//! Get dust relay fee.
virtual CFeeRate getDustRelayFee() = 0;
diff --git a/src/net.cpp b/src/net.cpp
index 54d572c68c..af2afa218e 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -16,6 +16,7 @@
#include <net_permissions.h>
#include <netbase.h>
#include <node/ui_interface.h>
+#include <optional.h>
#include <protocol.h>
#include <random.h>
#include <scheduler.h>
@@ -47,6 +48,12 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"
#include <math.h>
+/** Maximum number of block-relay-only anchor connections */
+static constexpr size_t MAX_BLOCK_RELAY_ONLY_ANCHORS = 2;
+static_assert (MAX_BLOCK_RELAY_ONLY_ANCHORS <= static_cast<size_t>(MAX_BLOCK_RELAY_ONLY_CONNECTIONS), "MAX_BLOCK_RELAY_ONLY_ANCHORS must not exceed MAX_BLOCK_RELAY_ONLY_CONNECTIONS.");
+/** Anchor IP address database file name */
+const char* const ANCHORS_DATABASE_FILENAME = "anchors.dat";
+
// How often to dump addresses to peers.dat
static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL{15};
@@ -66,6 +73,9 @@ static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS{11};
static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS{5};
static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" peers
+/** 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
@@ -105,7 +115,6 @@ static const uint64_t RANDOMIZER_ID_ADDRCACHE = 0x1cf2e4ddd306dda9ULL; // SHA256
//
bool fDiscover = true;
bool fListen = true;
-bool g_relay_txes = !DEFAULT_BLOCKSONLY;
RecursiveMutex cs_mapLocalHost;
std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost);
static bool vfLimited[NET_MAX] GUARDED_BY(cs_mapLocalHost) = {};
@@ -348,6 +357,11 @@ CNode* CConnman::FindNode(const CService& addr)
return nullptr;
}
+bool CConnman::AlreadyConnectedToAddress(const CAddress& addr)
+{
+ return FindNode(static_cast<CNetAddr>(addr)) || FindNode(addr.ToStringIPPort());
+}
+
bool CConnman::CheckIncomingNonce(uint64_t nonce)
{
LOCK(cs_vNodes);
@@ -552,6 +566,7 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
X(nServices);
X(addr);
X(addrBind);
+ stats.m_network = GetNetworkName(ConnectedThroughNetwork());
stats.m_mapped_as = addr.GetMappedAS(m_asmap);
if (m_tx_relay != nullptr) {
LOCK(m_tx_relay->cs_filter);
@@ -573,6 +588,8 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
}
stats.fInbound = IsInboundConn();
stats.m_manual_connection = IsManualConn();
+ X(m_bip152_highbandwidth_to);
+ X(m_bip152_highbandwidth_from);
X(nStartingHeight);
{
LOCK(cs_vSend);
@@ -617,34 +634,21 @@ void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
}
#undef X
-/**
- * Receive bytes from the buffer and deserialize them into messages.
- *
- * @param[in] pch A pointer to the raw data
- * @param[in] nBytes Size of the data
- * @param[out] complete Set True if at least one message has been
- * deserialized and is ready to be processed
- * @return True if the peer should stay connected,
- * False if the peer should be disconnected from.
- */
-bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete)
+bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete)
{
complete = false;
const auto time = GetTime<std::chrono::microseconds>();
LOCK(cs_vRecv);
nLastRecv = std::chrono::duration_cast<std::chrono::seconds>(time).count();
- nRecvBytes += nBytes;
- while (nBytes > 0) {
+ nRecvBytes += msg_bytes.size();
+ while (msg_bytes.size() > 0) {
// absorb network data
- int handled = m_deserializer->Read(pch, nBytes);
+ int handled = m_deserializer->Read(msg_bytes);
if (handled < 0) {
// Serious header problem, disconnect from the peer.
return false;
}
- pch += handled;
- nBytes -= handled;
-
if (m_deserializer->Complete()) {
// decompose a transport agnostic CNetMessage from the deserializer
uint32_t out_err_raw_size{0};
@@ -674,13 +678,13 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete
return true;
}
-int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes)
+int V1TransportDeserializer::readHeader(Span<const uint8_t> msg_bytes)
{
// copy data to temporary parsing buffer
unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos;
- unsigned int nCopy = std::min(nRemaining, nBytes);
+ unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
- memcpy(&hdrbuf[nHdrPos], pch, nCopy);
+ memcpy(&hdrbuf[nHdrPos], msg_bytes.data(), nCopy);
nHdrPos += nCopy;
// if header incomplete, exit
@@ -714,18 +718,18 @@ int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes)
return nCopy;
}
-int V1TransportDeserializer::readData(const char *pch, unsigned int nBytes)
+int V1TransportDeserializer::readData(Span<const uint8_t> msg_bytes)
{
unsigned int nRemaining = hdr.nMessageSize - nDataPos;
- unsigned int nCopy = std::min(nRemaining, nBytes);
+ unsigned int nCopy = std::min<unsigned int>(nRemaining, msg_bytes.size());
if (vRecv.size() < nDataPos + nCopy) {
// Allocate up to 256 KiB ahead, but never more than the total message size.
vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
}
- hasher.Write({(const unsigned char*)pch, nCopy});
- memcpy(&vRecv[nDataPos], pch, nCopy);
+ hasher.Write(msg_bytes.first(nCopy));
+ memcpy(&vRecv[nDataPos], msg_bytes.data(), nCopy);
nDataPos += nCopy;
return nCopy;
@@ -841,22 +845,6 @@ size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pno
return nSentSize;
}
-struct NodeEvictionCandidate
-{
- NodeId id;
- int64_t nTimeConnected;
- int64_t nMinPingUsecTime;
- int64_t nLastBlockTime;
- int64_t nLastTXTime;
- bool fRelevantServices;
- bool fRelayTxes;
- bool fBloomFilter;
- CAddress addr;
- uint64_t nKeyedNetGroup;
- bool prefer_evict;
- bool m_is_local;
-};
-
static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
{
return a.nMinPingUsecTime > b.nMinPingUsecTime;
@@ -912,43 +900,8 @@ static void EraseLastKElements(std::vector<T> &elements, Comparator comparator,
elements.erase(elements.end() - eraseSize, elements.end());
}
-/** 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.
- * The strategy used here is to protect a small number of peers
- * for each of several distinct characteristics which are difficult
- * to forge. In order to partition a node the attacker must be
- * simultaneously better at all of them than honest peers.
- */
-bool CConnman::AttemptToEvictConnection()
+[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates)
{
- std::vector<NodeEvictionCandidate> vEvictionCandidates;
- {
- LOCK(cs_vNodes);
-
- for (const CNode* node : vNodes) {
- if (node->HasPermission(PF_NOBAN))
- continue;
- if (!node->IsInboundConn())
- continue;
- if (node->fDisconnect)
- continue;
- bool peer_relay_txes = false;
- bool peer_filter_not_null = false;
- if (node->m_tx_relay != nullptr) {
- LOCK(node->m_tx_relay->cs_filter);
- peer_relay_txes = node->m_tx_relay->fRelayTxes;
- peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
- }
- NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
- node->nLastBlockTime, node->nLastTXTime,
- HasAllDesirableServiceFlags(node->nServices),
- peer_relay_txes, peer_filter_not_null, node->addr, node->nKeyedNetGroup,
- node->m_prefer_evict, node->addr.IsLocal()};
- vEvictionCandidates.push_back(candidate);
- }
- }
-
// Protect connections with certain characteristics
// Deterministically select 4 peers to protect by netgroup.
@@ -986,7 +939,7 @@ bool CConnman::AttemptToEvictConnection()
total_protect_size -= initial_size - vEvictionCandidates.size();
EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, total_protect_size);
- if (vEvictionCandidates.empty()) return false;
+ if (vEvictionCandidates.empty()) return 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)
@@ -1018,10 +971,52 @@ bool CConnman::AttemptToEvictConnection()
vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
// Disconnect from the network group with the most connections
- NodeId evicted = vEvictionCandidates.front().id;
+ 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.
+ * The strategy used here is to protect a small number of peers
+ * for each of several distinct characteristics which are difficult
+ * to forge. In order to partition a node the attacker must be
+ * simultaneously better at all of them than honest peers.
+ */
+bool CConnman::AttemptToEvictConnection()
+{
+ std::vector<NodeEvictionCandidate> vEvictionCandidates;
+ {
+
+ LOCK(cs_vNodes);
+ for (const CNode* node : vNodes) {
+ if (node->HasPermission(PF_NOBAN))
+ continue;
+ if (!node->IsInboundConn())
+ continue;
+ if (node->fDisconnect)
+ continue;
+ bool peer_relay_txes = false;
+ bool peer_filter_not_null = false;
+ if (node->m_tx_relay != nullptr) {
+ LOCK(node->m_tx_relay->cs_filter);
+ peer_relay_txes = node->m_tx_relay->fRelayTxes;
+ peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
+ }
+ NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
+ node->nLastBlockTime, node->nLastTXTime,
+ HasAllDesirableServiceFlags(node->nServices),
+ peer_relay_txes, peer_filter_not_null, node->nKeyedNetGroup,
+ node->m_prefer_evict, node->addr.IsLocal()};
+ vEvictionCandidates.push_back(candidate);
+ }
+ }
+ const Optional<NodeId> node_id_to_evict = SelectNodeToEvict(std::move(vEvictionCandidates));
+ if (!node_id_to_evict) {
+ return false;
+ }
LOCK(cs_vNodes);
for (CNode* pnode : vNodes) {
- if (pnode->GetId() == evicted) {
+ if (pnode->GetId() == *node_id_to_evict) {
pnode->fDisconnect = true;
return true;
}
@@ -1233,7 +1228,7 @@ void CConnman::InactivityCheck(CNode *pnode)
LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
pnode->fDisconnect = true;
}
- else if (nTime - pnode->nLastRecv > (pnode->GetCommonVersion() > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
+ else if (nTime - pnode->nLastRecv > TIMEOUT_INTERVAL)
{
LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
pnode->fDisconnect = true;
@@ -1465,18 +1460,18 @@ void CConnman::SocketHandler()
if (recvSet || errorSet)
{
// typical socket buffer is 8K-64K
- char pchBuf[0x10000];
+ uint8_t pchBuf[0x10000];
int nBytes = 0;
{
LOCK(pnode->cs_hSocket);
if (pnode->hSocket == INVALID_SOCKET)
continue;
- nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
+ nBytes = recv(pnode->hSocket, (char*)pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
}
if (nBytes > 0)
{
bool notify = false;
- if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify))
+ if (!pnode->ReceiveMsgBytes(Span<const uint8_t>(pchBuf, nBytes), notify))
pnode->CloseSocketDisconnect();
RecordBytesRecv(nBytes);
if (notify) {
@@ -1828,18 +1823,32 @@ void CConnman::SetTryNewOutboundPeer(bool flag)
// Also exclude peers that haven't finished initial connection handshake yet
// (so that we don't decide we're over our desired connection limit, and then
// evict some peer that has finished the handshake)
-int CConnman::GetExtraOutboundCount()
+int CConnman::GetExtraFullOutboundCount()
+{
+ int full_outbound_peers = 0;
+ {
+ LOCK(cs_vNodes);
+ for (const CNode* pnode : vNodes) {
+ if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsFullOutboundConn()) {
+ ++full_outbound_peers;
+ }
+ }
+ }
+ return std::max(full_outbound_peers - m_max_outbound_full_relay, 0);
+}
+
+int CConnman::GetExtraBlockRelayCount()
{
- int nOutbound = 0;
+ int block_relay_peers = 0;
{
LOCK(cs_vNodes);
for (const CNode* pnode : vNodes) {
- if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsOutboundOrBlockRelayConn()) {
- ++nOutbound;
+ if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsBlockOnlyConn()) {
+ ++block_relay_peers;
}
}
}
- return std::max(nOutbound - m_max_outbound_full_relay - m_max_outbound_block_relay, 0);
+ return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
}
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
@@ -1870,6 +1879,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
// Minimum time before next feeler connection (in microseconds).
int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
+ int64_t nNextExtraBlockRelay = PoissonNextSend(nStart*1000*1000, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
while (!interruptNet)
{
ProcessAddrFetch();
@@ -1932,23 +1942,53 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
int64_t nTime = GetTimeMicros();
+ bool anchor = false;
bool fFeeler = false;
// Determine what type of connection to open. Opening
- // OUTBOUND_FULL_RELAY connections gets the highest priority until we
+ // BLOCK_RELAY connections to addresses from anchors.dat gets the highest
+ // priority. Then we open OUTBOUND_FULL_RELAY priority until we
// meet our full-relay capacity. Then we open BLOCK_RELAY connection
// until we hit our block-relay-only peer limit.
// GetTryNewOutboundPeer() gets set when a stale tip is detected, so we
// try opening an additional OUTBOUND_FULL_RELAY connection. If none of
- // these conditions are met, check the nNextFeeler timer to decide if
- // we should open a FEELER.
+ // these conditions are met, check to see if it's time to try an extra
+ // block-relay-only peer (to confirm our tip is current, see below) or the nNextFeeler
+ // timer to decide if we should open a FEELER.
- if (nOutboundFullRelay < m_max_outbound_full_relay) {
+ if (!m_anchors.empty() && (nOutboundBlockRelay < m_max_outbound_block_relay)) {
+ conn_type = ConnectionType::BLOCK_RELAY;
+ anchor = true;
+ } else if (nOutboundFullRelay < m_max_outbound_full_relay) {
// OUTBOUND_FULL_RELAY
} else if (nOutboundBlockRelay < m_max_outbound_block_relay) {
conn_type = ConnectionType::BLOCK_RELAY;
} else if (GetTryNewOutboundPeer()) {
// OUTBOUND_FULL_RELAY
+ } else if (nTime > nNextExtraBlockRelay && m_start_extra_block_relay_peers) {
+ // Periodically connect to a peer (using regular outbound selection
+ // methodology from addrman) and stay connected long enough to sync
+ // headers, but not much else.
+ //
+ // Then disconnect the peer, if we haven't learned anything new.
+ //
+ // The idea is to make eclipse attacks very difficult to pull off,
+ // because every few minutes we're finding a new peer to learn headers
+ // from.
+ //
+ // This is similar to the logic for trying extra outbound (full-relay)
+ // peers, except:
+ // - we do this all the time on a poisson timer, rather than just when
+ // our tip is stale
+ // - we potentially disconnect our next-youngest block-relay-only peer, if our
+ // newest block-relay-only peer delivers a block more recently.
+ // See the eviction logic in net_processing.cpp.
+ //
+ // Because we can promote these connections to block-relay-only
+ // connections, they do not get their own ConnectionType enum
+ // (similar to how we deal with extra outbound peers).
+ nNextExtraBlockRelay = PoissonNextSend(nTime, EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL);
+ conn_type = ConnectionType::BLOCK_RELAY;
} else if (nTime > nNextFeeler) {
nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL);
conn_type = ConnectionType::FEELER;
@@ -1964,11 +2004,48 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
int nTries = 0;
while (!interruptNet)
{
- CAddrInfo addr = addrman.SelectTriedCollision();
+ if (anchor && !m_anchors.empty()) {
+ const CAddress addr = m_anchors.back();
+ m_anchors.pop_back();
+ if (!addr.IsValid() || IsLocal(addr) || !IsReachable(addr) ||
+ !HasAllDesirableServiceFlags(addr.nServices) ||
+ setConnected.count(addr.GetGroup(addrman.m_asmap))) continue;
+ addrConnect = addr;
+ LogPrint(BCLog::NET, "Trying to make an anchor connection to %s\n", addrConnect.ToString());
+ break;
+ }
- // SelectTriedCollision returns an invalid address if it is empty.
- if (!fFeeler || !addr.IsValid()) {
- addr = addrman.Select(fFeeler);
+ // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
+ // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
+ // already-connected network ranges, ...) before trying new addrman addresses.
+ nTries++;
+ if (nTries > 100)
+ break;
+
+ CAddrInfo addr;
+
+ if (fFeeler) {
+ // First, try to get a tried table collision address. This returns
+ // an empty (invalid) address if there are no collisions to try.
+ addr = addrman.SelectTriedCollision();
+
+ if (!addr.IsValid()) {
+ // No tried table collisions. Select a new table address
+ // for our feeler.
+ addr = addrman.Select(true);
+ } else if (AlreadyConnectedToAddress(addr)) {
+ // If test-before-evict logic would have us connect to a
+ // peer that we're already connected to, just mark that
+ // address as Good(). We won't be able to initiate the
+ // connection anyway, so this avoids inadvertently evicting
+ // a currently-connected peer.
+ addrman.Good(addr);
+ // Select a new table address for our feeler instead.
+ addr = addrman.Select(true);
+ }
+ } else {
+ // Not a feeler
+ addr = addrman.Select();
}
// Require outbound connections, other than feelers, to be to distinct network groups
@@ -1981,13 +2058,6 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
break;
}
- // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
- // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
- // already-connected network ranges, ...) before trying new addrman addresses.
- nTries++;
- if (nTries > 100)
- break;
-
if (!IsReachable(addr))
continue;
@@ -2027,6 +2097,19 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
}
}
+std::vector<CAddress> CConnman::GetCurrentBlockRelayOnlyConns() const
+{
+ std::vector<CAddress> ret;
+ LOCK(cs_vNodes);
+ for (const CNode* pnode : vNodes) {
+ if (pnode->IsBlockOnlyConn()) {
+ ret.push_back(pnode->addr);
+ }
+ }
+
+ return ret;
+}
+
std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo()
{
std::vector<AddedNodeInfo> ret;
@@ -2124,7 +2207,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
}
if (!pszDest) {
bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect));
- if (IsLocal(addrConnect) || FindNode(static_cast<CNetAddr>(addrConnect)) || banned_or_discouraged || FindNode(addrConnect.ToStringIPPort())) {
+ if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) {
return;
}
} else if (FindNode(std::string(pszDest)))
@@ -2386,17 +2469,6 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
{
Init(connOptions);
- {
- LOCK(cs_totalBytesRecv);
- nTotalBytesRecv = 0;
- }
- {
- LOCK(cs_totalBytesSent);
- nTotalBytesSent = 0;
- nMaxOutboundTotalBytesSentInCycle = 0;
- nMaxOutboundCycleStartTime = 0;
- }
-
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds, connOptions.onion_binds)) {
if (clientInterface) {
clientInterface->ThreadSafeMessageBox(
@@ -2426,6 +2498,15 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
}
}
+ if (m_use_addrman_outgoing) {
+ // Load addresses from anchors.dat
+ m_anchors = ReadAnchors(GetDataDir() / ANCHORS_DATABASE_FILENAME);
+ if (m_anchors.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
+ m_anchors.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
+ }
+ LogPrintf("%i block-relay-only anchors will be tried for connections.\n", m_anchors.size());
+ }
+
uiInterface.InitMessage(_("Starting network threads...").translated);
fAddressesInitialized = true;
@@ -2541,6 +2622,15 @@ void CConnman::StopNodes()
if (fAddressesInitialized) {
DumpAddresses();
fAddressesInitialized = false;
+
+ if (m_use_addrman_outgoing) {
+ // Anchor connections are only dumped during clean shutdown.
+ std::vector<CAddress> anchors_to_dump = GetCurrentBlockRelayOnlyConns();
+ if (anchors_to_dump.size() > MAX_BLOCK_RELAY_ONLY_ANCHORS) {
+ anchors_to_dump.resize(MAX_BLOCK_RELAY_ONLY_ANCHORS);
+ }
+ DumpAnchors(GetDataDir() / ANCHORS_DATABASE_FILENAME, anchors_to_dump);
+ }
}
// Close sockets
@@ -2570,7 +2660,7 @@ void CConnman::DeleteNode(CNode* pnode)
{
assert(pnode);
bool fUpdateConnectionTime = false;
- m_msgproc->FinalizeNode(pnode->GetId(), fUpdateConnectionTime);
+ m_msgproc->FinalizeNode(*pnode, fUpdateConnectionTime);
if (fUpdateConnectionTime) {
addrman.Connected(pnode->addr);
}
@@ -2753,8 +2843,8 @@ void CConnman::RecordBytesSent(uint64_t bytes)
LOCK(cs_totalBytesSent);
nTotalBytesSent += bytes;
- uint64_t now = GetTime();
- if (nMaxOutboundCycleStartTime + nMaxOutboundTimeframe < now)
+ const auto now = GetTime<std::chrono::seconds>();
+ if (nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME < now)
{
// timeframe expired, reset cycle
nMaxOutboundCycleStartTime = now;
@@ -2765,48 +2855,29 @@ void CConnman::RecordBytesSent(uint64_t bytes)
nMaxOutboundTotalBytesSentInCycle += bytes;
}
-void CConnman::SetMaxOutboundTarget(uint64_t limit)
-{
- LOCK(cs_totalBytesSent);
- nMaxOutboundLimit = limit;
-}
-
uint64_t CConnman::GetMaxOutboundTarget()
{
LOCK(cs_totalBytesSent);
return nMaxOutboundLimit;
}
-uint64_t CConnman::GetMaxOutboundTimeframe()
+std::chrono::seconds CConnman::GetMaxOutboundTimeframe()
{
- LOCK(cs_totalBytesSent);
- return nMaxOutboundTimeframe;
+ return MAX_UPLOAD_TIMEFRAME;
}
-uint64_t CConnman::GetMaxOutboundTimeLeftInCycle()
+std::chrono::seconds CConnman::GetMaxOutboundTimeLeftInCycle()
{
LOCK(cs_totalBytesSent);
if (nMaxOutboundLimit == 0)
- return 0;
+ return 0s;
- if (nMaxOutboundCycleStartTime == 0)
- return nMaxOutboundTimeframe;
-
- uint64_t cycleEndTime = nMaxOutboundCycleStartTime + nMaxOutboundTimeframe;
- uint64_t now = GetTime();
- return (cycleEndTime < now) ? 0 : cycleEndTime - GetTime();
-}
+ if (nMaxOutboundCycleStartTime.count() == 0)
+ return MAX_UPLOAD_TIMEFRAME;
-void CConnman::SetMaxOutboundTimeframe(uint64_t timeframe)
-{
- LOCK(cs_totalBytesSent);
- if (nMaxOutboundTimeframe != timeframe)
- {
- // reset measure-cycle in case of changing
- // the timeframe
- nMaxOutboundCycleStartTime = GetTime();
- }
- nMaxOutboundTimeframe = timeframe;
+ const std::chrono::seconds cycleEndTime = nMaxOutboundCycleStartTime + MAX_UPLOAD_TIMEFRAME;
+ const auto now = GetTime<std::chrono::seconds>();
+ return (cycleEndTime < now) ? 0s : cycleEndTime - now;
}
bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit)
@@ -2818,8 +2889,8 @@ bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit)
if (historicalBlockServingLimit)
{
// keep a large enough buffer to at least relay each block once
- uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
- uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SERIALIZED_SIZE;
+ const std::chrono::seconds timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
+ const uint64_t buffer = timeLeftInCycle / std::chrono::minutes{10} * MAX_BLOCK_SERIALIZED_SIZE;
if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
return true;
}
@@ -2869,18 +2940,15 @@ unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
: nTimeConnected(GetSystemTimeInSeconds()),
- addr(addrIn),
- addrBind(addrBindIn),
- nKeyedNetGroup(nKeyedNetGroupIn),
- // Don't relay addr messages to peers that we connect to as block-relay-only
- // peers (to prevent adversaries from inferring these links from addr
- // traffic).
- id(idIn),
- nLocalHostNonce(nLocalHostNonceIn),
- m_conn_type(conn_type_in),
- nLocalServices(nLocalServicesIn),
- nMyStartingHeight(nMyStartingHeightIn),
- m_inbound_onion(inbound_onion)
+ addr(addrIn),
+ addrBind(addrBindIn),
+ nKeyedNetGroup(nKeyedNetGroupIn),
+ id(idIn),
+ nLocalHostNonce(nLocalHostNonceIn),
+ m_conn_type(conn_type_in),
+ nLocalServices(nLocalServicesIn),
+ nMyStartingHeight(nMyStartingHeightIn),
+ m_inbound_onion(inbound_onion)
{
hSocket = hSocketIn;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
diff --git a/src/net.h b/src/net.h
index 4ba872d02c..b7c45abb09 100644
--- a/src/net.h
+++ b/src/net.h
@@ -24,19 +24,16 @@
#include <sync.h>
#include <threadinterrupt.h>
#include <uint256.h>
+#include <util/check.h>
#include <atomic>
+#include <condition_variable>
#include <cstdint>
#include <deque>
#include <map>
-#include <thread>
#include <memory>
-#include <condition_variable>
-
-#ifndef WIN32
-#include <arpa/inet.h>
-#endif
-
+#include <thread>
+#include <vector>
class CScheduler;
class CNode;
@@ -52,6 +49,8 @@ static const bool DEFAULT_WHITELISTFORCERELAY = false;
static const int TIMEOUT_INTERVAL = 20 * 60;
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/
static const int FEELER_INTERVAL = 120;
+/** Run the extra block-relay-only connection loop once every 5 minutes. **/
+static const int EXTRA_BLOCK_RELAY_ONLY_PEER_INTERVAL = 300;
/** The maximum number of addresses from our addrman to return in response to a getaddr message. */
static constexpr size_t MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 4 MB is currently acceptable). */
@@ -77,9 +76,7 @@ static const bool DEFAULT_UPNP = false;
/** The maximum number of peer connections to maintain. */
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125;
/** The default for -maxuploadtarget. 0 = Unlimited */
-static const uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0;
-/** The default timeframe for -maxuploadtarget. 1 day. */
-static const uint64_t MAX_UPLOAD_TIMEFRAME = 60 * 60 * 24;
+static constexpr uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0;
/** Default for blocks only*/
static const bool DEFAULT_BLOCKSONLY = false;
/** -peertimeout default */
@@ -115,17 +112,12 @@ struct CSerializedNetMsg
std::string m_type;
};
-const std::vector<std::string> CONNECTION_TYPE_DOC{
- "outbound-full-relay (default automatic connections)",
- "block-relay-only (does not relay transactions or addresses)",
- "inbound (initiated by the peer)",
- "manual (added via addnode RPC or -addnode/-connect configuration options)",
- "addr-fetch (short-lived automatic connection for soliciting addresses)",
- "feeler (short-lived automatic connection for testing addresses)"};
-
/** 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. */
+ * 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. */
enum class ConnectionType {
/**
* Inbound connections are those initiated by a peer. This is the only
@@ -173,7 +165,9 @@ enum class ConnectionType {
* 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_CONNECTIONS using addresses from our AddrMan.
+ * 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,
@@ -212,7 +206,6 @@ public:
BanMan* m_banman = nullptr;
unsigned int nSendBufferMaxSize = 0;
unsigned int nReceiveFloodSize = 0;
- uint64_t nMaxOutboundTimeframe = 0;
uint64_t nMaxOutboundLimit = 0;
int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT;
std::vector<std::string> vSeedNodes;
@@ -244,7 +237,6 @@ public:
m_peer_connect_timeout = connOptions.m_peer_connect_timeout;
{
LOCK(cs_totalBytesSent);
- nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe;
nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
}
vWhitelistedRange = connOptions.vWhitelistedRange;
@@ -337,13 +329,20 @@ public:
void SetTryNewOutboundPeer(bool flag);
bool GetTryNewOutboundPeer();
+ void StartExtraBlockRelayPeers() {
+ LogPrint(BCLog::NET, "net: enabling extra block-relay-only peers\n");
+ m_start_extra_block_relay_peers = true;
+ }
+
// Return the number of outbound peers we have in excess of our target (eg,
// if we previously called SetTryNewOutboundPeer(true), and have since set
// to false, we may have extra peers that we wish to disconnect). This may
// return a value less than (num_outbound_connections - num_outbound_slots)
// in cases where some outbound connections are not yet fully connected, or
// not yet fully disconnected.
- int GetExtraOutboundCount();
+ int GetExtraFullOutboundCount();
+ // Count the number of block-relay-only peers we have over our limit.
+ int GetExtraBlockRelayCount();
bool AddNode(const std::string& node);
bool RemoveAddedNode(const std::string& node);
@@ -364,13 +363,8 @@ public:
//! that peer during `net_processing.cpp:PushNodeVersion()`.
ServiceFlags GetLocalServices() const;
- //!set the max outbound target in bytes
- void SetMaxOutboundTarget(uint64_t limit);
uint64_t GetMaxOutboundTarget();
-
- //!set the timeframe for the max outbound target
- void SetMaxOutboundTimeframe(uint64_t timeframe);
- uint64_t GetMaxOutboundTimeframe();
+ std::chrono::seconds GetMaxOutboundTimeframe();
//! check if the outbound target is reached
//! if param historicalBlockServingLimit is set true, the function will
@@ -381,9 +375,9 @@ public:
//! in case of no limit, it will always response 0
uint64_t GetOutboundTargetBytesLeft();
- //! response the time in second left in the current max outbound cycle
- //! in case of no limit, it will always response 0
- uint64_t GetMaxOutboundTimeLeftInCycle();
+ //! returns the time left in the current max outbound cycle
+ //! in case of no limit, it will always return 0
+ std::chrono::seconds GetMaxOutboundTimeLeftInCycle();
uint64_t GetTotalBytesRecv();
uint64_t GetTotalBytesSent();
@@ -445,6 +439,12 @@ private:
CNode* FindNode(const std::string& addrName);
CNode* FindNode(const CService& addr);
+ /**
+ * Determine whether we're already connected to a given address, in order to
+ * avoid initiating duplicate connections.
+ */
+ bool AlreadyConnectedToAddress(const CAddress& addr);
+
bool AttemptToEvictConnection();
CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type);
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const;
@@ -460,6 +460,11 @@ private:
void RecordBytesRecv(uint64_t bytes);
void RecordBytesSent(uint64_t bytes);
+ /**
+ * Return vector of current BLOCK_RELAY peers.
+ */
+ std::vector<CAddress> GetCurrentBlockRelayOnlyConns() const;
+
// Whether the node should be passed out in ForEach* callbacks
static bool NodeFullyConnected(const CNode* pnode);
@@ -470,10 +475,9 @@ private:
uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent) {0};
// outbound limit & stats
- uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent);
- uint64_t nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent);
+ uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent) {0};
+ std::chrono::seconds nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent) {0};
uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent);
- uint64_t nMaxOutboundTimeframe GUARDED_BY(cs_totalBytesSent);
// P2P timeout in seconds
int64_t m_peer_connect_timeout;
@@ -561,6 +565,12 @@ private:
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
BanMan* m_banman;
+ /**
+ * Addresses that were saved during the previous clean shutdown. We'll
+ * attempt to make block-relay-only connections to them.
+ */
+ std::vector<CAddress> m_anchors;
+
/** SipHasher seeds for deterministic randomness */
const uint64_t nSeed0, nSeed1;
@@ -584,6 +594,12 @@ private:
* This takes the place of a feeler connection */
std::atomic_bool m_try_another_outbound_peer;
+ /** flag for initiating extra block-relay-only peer connections.
+ * this should only be enabled after initial chain sync has occurred,
+ * as these connections are intended to be short-lived and low-bandwidth.
+ */
+ std::atomic_bool m_start_extra_block_relay_peers{false};
+
std::atomic<int64_t> m_next_send_inv_to_incoming{0};
/**
@@ -610,7 +626,7 @@ public:
virtual bool ProcessMessages(CNode* pnode, std::atomic<bool>& interrupt) = 0;
virtual bool SendMessages(CNode* pnode) = 0;
virtual void InitializeNode(CNode* pnode) = 0;
- virtual void FinalizeNode(NodeId id, bool& update_connection_time) = 0;
+ virtual void FinalizeNode(const CNode& node, bool& update_connection_time) = 0;
protected:
/**
@@ -655,7 +671,6 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
extern bool fDiscover;
extern bool fListen;
-extern bool g_relay_txes;
/** Subversion as sent to the P2P network in `version` messages */
extern std::string strSubVersion;
@@ -688,6 +703,8 @@ public:
std::string cleanSubVer;
bool fInbound;
bool m_manual_connection;
+ bool m_bip152_highbandwidth_to;
+ bool m_bip152_highbandwidth_from;
int nStartingHeight;
uint64_t nSendBytes;
mapMsgCmdSize mapSendBytesPerMsgCmd;
@@ -705,6 +722,8 @@ public:
CAddress addr;
// Bind address of our side of the connection
CAddress addrBind;
+ // Name of the network the peer connected through
+ std::string m_network;
uint32_t m_mapped_as;
std::string m_conn_type_string;
};
@@ -741,8 +760,8 @@ public:
virtual bool Complete() const = 0;
// set the serialization context version
virtual void SetVersion(int version) = 0;
- // read and deserialize data
- virtual int Read(const char *data, unsigned int bytes) = 0;
+ /** read and deserialize data, advances msg_bytes data pointer */
+ virtual int Read(Span<const uint8_t>& msg_bytes) = 0;
// decomposes a message from the context
virtual Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err) = 0;
virtual ~TransportDeserializer() {}
@@ -763,8 +782,8 @@ private:
unsigned int nDataPos;
const uint256& GetMessageHash() const;
- int readHeader(const char *pch, unsigned int nBytes);
- int readData(const char *pch, unsigned int nBytes);
+ int readHeader(Span<const uint8_t> msg_bytes);
+ int readData(Span<const uint8_t> msg_bytes);
void Reset() {
vRecv.clear();
@@ -798,9 +817,14 @@ public:
hdrbuf.SetVersion(nVersionIn);
vRecv.SetVersion(nVersionIn);
}
- int Read(const char *pch, unsigned int nBytes) override {
- int ret = in_data ? readData(pch, nBytes) : readHeader(pch, nBytes);
- if (ret < 0) Reset();
+ int Read(Span<const uint8_t>& msg_bytes) override
+ {
+ int ret = in_data ? readData(msg_bytes) : readHeader(msg_bytes);
+ if (ret < 0) {
+ Reset();
+ } else {
+ msg_bytes = msg_bytes.subspan(ret);
+ }
return ret;
}
Optional<CNetMessage> GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) override;
@@ -847,7 +871,6 @@ public:
RecursiveMutex cs_sendProcessing;
- std::deque<CInv> vRecvGetData;
uint64_t nRecvBytes GUARDED_BY(cs_vRecv){0};
std::atomic<int64_t> nLastSend{0};
@@ -932,6 +955,9 @@ public:
/* Whether we send addr messages over this connection */
bool RelayAddrsWithConn() const
{
+ // Don't relay addr messages to peers that we connect to as block-relay-only
+ // peers (to prevent adversaries from inferring these links from addr
+ // traffic).
return m_conn_type != ConnectionType::BLOCK_RELAY;
}
@@ -969,6 +995,10 @@ protected:
public:
uint256 hashContinue;
std::atomic<int> nStartingHeight{-1};
+ // We selected peer as (compact blocks) high-bandwidth peer (BIP152)
+ std::atomic<bool> m_bip152_highbandwidth_to{false};
+ // Peer selected us as (compact blocks) high-bandwidth peer (BIP152)
+ std::atomic<bool> m_bip152_highbandwidth_from{false};
// flood relay
std::vector<CAddress> vAddrToSend;
@@ -1000,7 +1030,7 @@ public:
// Used for BIP35 mempool sending
bool fSendMempool GUARDED_BY(cs_tx_inventory){false};
// Last time a "MEMPOOL" request was serviced.
- std::atomic<std::chrono::seconds> m_last_mempool_req{std::chrono::seconds{0}};
+ std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
std::chrono::microseconds nNextInvSend{0};
RecursiveMutex cs_feeFilter;
@@ -1033,7 +1063,7 @@ public:
// The pong reply we're expecting, or 0 if no pong expected.
std::atomic<uint64_t> nPingNonceSent{0};
/** When the last ping was sent, or 0 if no ping was ever sent */
- std::atomic<std::chrono::microseconds> m_ping_start{std::chrono::microseconds{0}};
+ std::atomic<std::chrono::microseconds> m_ping_start{0us};
// Last measured round-trip time.
std::atomic<int64_t> nPingUsecTime{0};
// Best measured round-trip time.
@@ -1041,8 +1071,6 @@ public:
// Whether a ping is requested.
std::atomic<bool> fPingQueued{false};
- std::set<uint256> orphan_work_set;
-
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion = false);
~CNode();
CNode(const CNode&) = delete;
@@ -1105,10 +1133,20 @@ public:
return nRefCount;
}
- bool ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete);
+ /**
+ * Receive bytes from the buffer and deserialize them into messages.
+ *
+ * @param[in] msg_bytes The raw data
+ * @param[out] complete Set True if at least one message has been
+ * deserialized and is ready to be processed
+ * @return True if the peer should stay connected,
+ * False if the peer should be disconnected from.
+ */
+ bool ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete);
void SetCommonVersion(int greatest_common_version)
{
+ Assume(m_greatest_common_version == INIT_PROTO_VERSION);
m_greatest_common_version = greatest_common_version;
}
int GetCommonVersion() const
@@ -1139,18 +1177,23 @@ public:
m_addr_known->insert(_addr.GetKey());
}
- void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
+ /**
+ * Whether the peer supports the address. For example, a peer that does not
+ * implement BIP155 cannot receive Tor v3 addresses because it requires
+ * ADDRv2 (BIP155) encoding.
+ */
+ bool IsAddrCompatible(const CAddress& addr) const
{
- // Whether the peer supports the address in `_addr`. For example,
- // nodes that do not implement BIP155 cannot receive Tor v3 addresses
- // because they require ADDRv2 (BIP155) encoding.
- const bool addr_format_supported = m_wants_addrv2 || _addr.IsAddrV1Compatible();
+ return m_wants_addrv2 || addr.IsAddrV1Compatible();
+ }
+ void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
+ {
// Known checking here is only to save space from duplicates.
// SendMessages will filter it again for knowns that were added
// after addresses were pushed.
assert(m_addr_known);
- if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey()) && addr_format_supported) {
+ if (_addr.IsValid() && !m_addr_known->contains(_addr.GetKey()) && IsAddrCompatible(_addr)) {
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr;
} else {
@@ -1202,4 +1245,21 @@ inline std::chrono::microseconds PoissonNextSend(std::chrono::microseconds now,
return std::chrono::microseconds{PoissonNextSend(now.count(), average_interval.count())};
}
+struct NodeEvictionCandidate
+{
+ NodeId id;
+ int64_t nTimeConnected;
+ int64_t nMinPingUsecTime;
+ int64_t nLastBlockTime;
+ int64_t nLastTXTime;
+ bool fRelevantServices;
+ bool fRelayTxes;
+ bool fBloomFilter;
+ uint64_t nKeyedNetGroup;
+ bool prefer_evict;
+ bool m_is_local;
+};
+
+[[nodiscard]] Optional<NodeId> SelectNodeToEvict(std::vector<NodeEvictionCandidate>&& vEvictionCandidates);
+
#endif // BITCOIN_NET_H
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index f14db379fb..a33c4a0bd4 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -290,8 +290,6 @@ namespace {
struct CNodeState {
//! The peer's address
const CService address;
- //! Whether we have a fully established connection.
- bool fCurrentlyConnected;
//! The best known block we know this peer has announced.
const CBlockIndex *pindexBestKnownBlock;
//! The hash of the last unknown block this peer has announced.
@@ -378,19 +376,15 @@ struct CNodeState {
//! Whether this peer is an inbound connection
bool m_is_inbound;
- //! Whether this peer is a manual connection
- bool m_is_manual_connection;
-
//! A rolling bloom filter of all announced tx CInvs to this peer.
CRollingBloomFilter m_recently_announced_invs = CRollingBloomFilter{INVENTORY_MAX_RECENT_RELAY, 0.000001};
//! Whether this peer relays txs via wtxid
bool m_wtxid_relay{false};
- CNodeState(CAddress addrIn, bool is_inbound, bool is_manual)
- : address(addrIn), m_is_inbound(is_inbound), m_is_manual_connection(is_manual)
+ CNodeState(CAddress addrIn, bool is_inbound)
+ : address(addrIn), m_is_inbound(is_inbound)
{
- fCurrentlyConnected = false;
pindexBestKnownBlock = nullptr;
hashLastUnknownBlock.SetNull();
pindexLastCommonBlock = nullptr;
@@ -425,50 +419,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
return &it->second;
}
-/**
- * Data structure for an individual peer. This struct is not protected by
- * cs_main since it does not contain validation-critical data.
- *
- * Memory is owned by shared pointers and this object is destructed when
- * the refcount drops to zero.
- *
- * TODO: move most members from CNodeState to this structure.
- * TODO: move remaining application-layer data members from CNode to this structure.
- */
-struct Peer {
- /** Same id as the CNode object for this peer */
- const NodeId m_id{0};
-
- /** Protects misbehavior data members */
- Mutex m_misbehavior_mutex;
- /** Accumulated misbehavior score for this peer */
- int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
- /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
- bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
-
- Peer(NodeId id) : m_id(id) {}
-};
-
-using PeerRef = std::shared_ptr<Peer>;
-
-/**
- * Map of all Peer objects, keyed by peer id. This map is protected
- * by the global g_peer_mutex. Once a shared pointer reference is
- * taken, the lock may be released. Individual fields are protected by
- * their own locks.
- */
-Mutex g_peer_mutex;
-static std::map<NodeId, PeerRef> g_peer_map GUARDED_BY(g_peer_mutex);
-
-/** Get a shared pointer to the Peer object.
- * May return nullptr if the Peer object can't be found. */
-static PeerRef GetPeerRef(NodeId id)
-{
- LOCK(g_peer_mutex);
- auto it = g_peer_map.find(id);
- return it != g_peer_map.end() ? it->second : nullptr;
-}
-
static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
nPreferredDownload -= state->fPreferredDownload;
@@ -479,30 +429,6 @@ static void UpdatePreferredDownload(const CNode& node, CNodeState* state) EXCLUS
nPreferredDownload += state->fPreferredDownload;
}
-static void PushNodeVersion(CNode& pnode, CConnman& connman, int64_t nTime)
-{
- // Note that pnode->GetLocalServices() is a reflection of the local
- // services we were offering when the CNode object was created for this
- // peer.
- ServiceFlags nLocalNodeServices = pnode.GetLocalServices();
- uint64_t nonce = pnode.GetLocalNonce();
- int nNodeStartingHeight = pnode.GetMyStartingHeight();
- NodeId nodeid = pnode.GetId();
- CAddress addr = pnode.addr;
-
- CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService(), addr.nServices));
- CAddress addrMe = CAddress(CService(), nLocalNodeServices);
-
- connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
- nonce, strSubVersion, nNodeStartingHeight, ::g_relay_txes && pnode.m_tx_relay != nullptr));
-
- if (fLogIPs) {
- LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
- } else {
- LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid);
- }
-}
-
// Returns a bool indicating whether we requested this block.
// Also used if a block was /not/ received and timed out or started with another peer
static bool MarkBlockAsReceived(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
@@ -628,11 +554,15 @@ static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connma
// blocks using compact encodings.
connman.ForNode(lNodesAnnouncingHeaderAndIDs.front(), [&connman, nCMPCTBLOCKVersion](CNode* pnodeStop){
connman.PushMessage(pnodeStop, CNetMsgMaker(pnodeStop->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/false, nCMPCTBLOCKVersion));
+ // save BIP152 bandwidth state: we select peer to be low-bandwidth
+ pnodeStop->m_bip152_highbandwidth_to = false;
return true;
});
lNodesAnnouncingHeaderAndIDs.pop_front();
}
connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetCommonVersion()).Make(NetMsgType::SENDCMPCT, /*fAnnounceUsingCMPCTBLOCK=*/true, nCMPCTBLOCKVersion));
+ // save BIP152 bandwidth state: we select peer to be high-bandwidth
+ pfrom->m_bip152_highbandwidth_to = true;
lNodesAnnouncingHeaderAndIDs.push_back(pfrom->GetId());
return true;
});
@@ -753,6 +683,32 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
} // namespace
+void PeerManager::PushNodeVersion(CNode& pnode, int64_t nTime)
+{
+ // Note that pnode->GetLocalServices() is a reflection of the local
+ // services we were offering when the CNode object was created for this
+ // peer.
+ ServiceFlags nLocalNodeServices = pnode.GetLocalServices();
+ uint64_t nonce = pnode.GetLocalNonce();
+ int nNodeStartingHeight = pnode.GetMyStartingHeight();
+ NodeId nodeid = pnode.GetId();
+ CAddress addr = pnode.addr;
+
+ CAddress addrYou = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ?
+ addr :
+ CAddress(CService(), addr.nServices);
+ CAddress addrMe = CAddress(CService(), nLocalNodeServices);
+
+ m_connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe,
+ nonce, strSubVersion, nNodeStartingHeight, !m_ignore_incoming_txs && pnode.m_tx_relay != nullptr));
+
+ if (fLogIPs) {
+ LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid);
+ } else {
+ LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid);
+ }
+}
+
void PeerManager::AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std::chrono::microseconds current_time)
{
AssertLockHeld(::cs_main); // For m_txrequest
@@ -795,16 +751,16 @@ void PeerManager::InitializeNode(CNode *pnode) {
NodeId nodeid = pnode->GetId();
{
LOCK(cs_main);
- mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, pnode->IsInboundConn(), pnode->IsManualConn()));
+ mapNodeState.emplace_hint(mapNodeState.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(addr, pnode->IsInboundConn()));
assert(m_txrequest.Count(nodeid) == 0);
}
{
PeerRef peer = std::make_shared<Peer>(nodeid);
- LOCK(g_peer_mutex);
- g_peer_map.emplace_hint(g_peer_map.end(), nodeid, std::move(peer));
+ LOCK(m_peer_mutex);
+ m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
}
if (!pnode->IsInboundConn()) {
- PushNodeVersion(*pnode, m_connman, GetTime());
+ PushNodeVersion(*pnode, GetTime());
}
}
@@ -829,16 +785,15 @@ void PeerManager::ReattemptInitialBroadcast(CScheduler& scheduler) const
scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
}
-void PeerManager::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
+void PeerManager::FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) {
+ NodeId nodeid = node.GetId();
fUpdateConnectionTime = false;
LOCK(cs_main);
int misbehavior{0};
{
- PeerRef peer = GetPeerRef(nodeid);
+ PeerRef peer = RemovePeer(nodeid);
assert(peer != nullptr);
misbehavior = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_misbehavior_score);
- LOCK(g_peer_mutex);
- g_peer_map.erase(nodeid);
}
CNodeState *state = State(nodeid);
assert(state != nullptr);
@@ -846,7 +801,9 @@ void PeerManager::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
if (state->fSyncStarted)
nSyncStarted--;
- if (misbehavior == 0 && state->fCurrentlyConnected) {
+ if (node.fSuccessfullyConnected && misbehavior == 0 &&
+ !node.IsBlockOnlyConn() && !node.IsInboundConn()) {
+ // Only change visible addrman state for outbound, full-relay peers
fUpdateConnectionTime = true;
}
@@ -877,7 +834,26 @@ void PeerManager::FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) {
LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid);
}
-bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
+PeerRef PeerManager::GetPeerRef(NodeId id) const
+{
+ LOCK(m_peer_mutex);
+ auto it = m_peer_map.find(id);
+ return it != m_peer_map.end() ? it->second : nullptr;
+}
+
+PeerRef PeerManager::RemovePeer(NodeId id)
+{
+ PeerRef ret;
+ LOCK(m_peer_mutex);
+ auto it = m_peer_map.find(id);
+ if (it != m_peer_map.end()) {
+ ret = std::move(it->second);
+ m_peer_map.erase(it);
+ }
+ return ret;
+}
+
+bool PeerManager::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
{
LOCK(cs_main);
CNodeState* state = State(nodeid);
@@ -1075,8 +1051,8 @@ bool PeerManager::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationSt
}
// Discourage outbound (but not inbound) peers if on an invalid chain.
- // Exempt HB compact block peers and manual connections.
- if (!via_compact_block && !node_state->m_is_inbound && !node_state->m_is_manual_connection) {
+ // 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);
return true;
}
@@ -1149,13 +1125,15 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para
}
PeerManager::PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool)
+ CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
+ bool ignore_incoming_txs)
: m_chainparams(chainparams),
m_connman(connman),
m_banman(banman),
m_chainman(chainman),
m_mempool(pool),
- m_stale_tip_check_time(0)
+ m_stale_tip_check_time(0),
+ m_ignore_incoming_txs(ignore_incoming_txs)
{
// Initialize global variables that cannot be constructed at startup.
recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
@@ -1312,34 +1290,33 @@ void PeerManager::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_
* in ::ChainActive() to our peers.
*/
void PeerManager::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {
- const int nNewHeight = pindexNew->nHeight;
- m_connman.SetBestHeight(nNewHeight);
-
+ m_connman.SetBestHeight(pindexNew->nHeight);
SetServiceFlagsIBDCache(!fInitialDownload);
- if (!fInitialDownload) {
- // Find the hashes of all blocks that weren't previously in the best chain.
- std::vector<uint256> vHashes;
- const CBlockIndex *pindexToAnnounce = pindexNew;
- while (pindexToAnnounce != pindexFork) {
- vHashes.push_back(pindexToAnnounce->GetBlockHash());
- pindexToAnnounce = pindexToAnnounce->pprev;
- if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
- // Limit announcements in case of a huge reorganization.
- // Rely on the peer's synchronization mechanism in that case.
- break;
- }
+
+ // Don't relay inventory during initial block download.
+ if (fInitialDownload) return;
+
+ // Find the hashes of all blocks that weren't previously in the best chain.
+ std::vector<uint256> vHashes;
+ const CBlockIndex *pindexToAnnounce = pindexNew;
+ while (pindexToAnnounce != pindexFork) {
+ vHashes.push_back(pindexToAnnounce->GetBlockHash());
+ pindexToAnnounce = pindexToAnnounce->pprev;
+ if (vHashes.size() == MAX_BLOCKS_TO_ANNOUNCE) {
+ // Limit announcements in case of a huge reorganization.
+ // Rely on the peer's synchronization mechanism in that case.
+ break;
}
- // Relay inventory, but don't relay old inventory during initial block download.
- m_connman.ForEachNode([nNewHeight, &vHashes](CNode* pnode) {
- LOCK(pnode->cs_inventory);
- if (nNewHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : 0)) {
- for (const uint256& hash : reverse_iterate(vHashes)) {
- pnode->vBlockHashesToAnnounce.push_back(hash);
- }
- }
- });
- m_connman.WakeMessageHandler();
}
+
+ // Relay to all peers
+ m_connman.ForEachNode([&vHashes](CNode* pnode) {
+ LOCK(pnode->cs_inventory);
+ for (const uint256& hash : reverse_iterate(vHashes)) {
+ pnode->vBlockHashesToAnnounce.push_back(hash);
+ }
+ });
+ m_connman.WakeMessageHandler();
}
/**
@@ -1433,7 +1410,23 @@ void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman&
});
}
-static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
+/**
+ * Relay (gossip) an address to a few randomly chosen nodes.
+ * We choose the same nodes within a given 24h window (if the list of connected
+ * nodes does not change) and we don't relay to nodes that already know an
+ * address. So within 24h we will likely relay a given address once. This is to
+ * prevent a peer from unjustly giving their address better propagation by sending
+ * it to us repeatedly.
+ * @param[in] originator The peer that sent us the address. We don't want to relay it back.
+ * @param[in] addr Address to relay.
+ * @param[in] fReachable Whether the address' network is reachable. We relay unreachable
+ * addresses less.
+ * @param[in] connman Connection manager to choose nodes to relay to.
+ */
+static void RelayAddress(const CNode& originator,
+ const CAddress& addr,
+ bool fReachable,
+ const CConnman& connman)
{
if (!fReachable && !addr.IsRelayable()) return;
@@ -1450,8 +1443,8 @@ static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman&
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
assert(nRelayNodes <= best.size());
- auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
- if (pnode->RelayAddrsWithConn()) {
+ auto sortfunc = [&best, &hasher, nRelayNodes, &originator, &addr](CNode* pnode) {
+ if (pnode->RelayAddrsWithConn() && pnode != &originator && pnode->IsAddrCompatible(addr)) {
uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
for (unsigned int i = 0; i < nRelayNodes; i++) {
if (hashKey > best[i].first) {
@@ -1654,11 +1647,11 @@ static CTransactionRef FindTxForGetData(const CTxMemPool& mempool, const CNode&
return {};
}
-void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
+void static ProcessGetData(CNode& pfrom, Peer& peer, const CChainParams& chainparams, CConnman& connman, CTxMemPool& mempool, const std::atomic<bool>& interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(!cs_main, peer.m_getdata_requests_mutex)
{
AssertLockNotHeld(cs_main);
- std::deque<CInv>::iterator it = pfrom.vRecvGetData.begin();
+ std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
std::vector<CInv> vNotFound;
const CNetMsgMaker msgMaker(pfrom.GetCommonVersion());
@@ -1670,7 +1663,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm
// Process as many TX items from the front of the getdata queue as
// possible, since they're common and it's efficient to batch process
// them.
- while (it != pfrom.vRecvGetData.end() && it->IsGenTxMsg()) {
+ while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
if (interruptMsgProc) return;
// The send buffer provides backpressure. If there's no space in
// the buffer, pause processing until the next call.
@@ -1718,7 +1711,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm
// Only process one BLOCK item per call, since they're uncommon and can be
// expensive to process.
- if (it != pfrom.vRecvGetData.end() && !pfrom.fPauseSend) {
+ if (it != peer.m_getdata_requests.end() && !pfrom.fPauseSend) {
const CInv &inv = *it++;
if (inv.IsGenBlkMsg()) {
ProcessGetBlockData(pfrom, chainparams, inv, connman);
@@ -1727,7 +1720,7 @@ void static ProcessGetData(CNode& pfrom, const CChainParams& chainparams, CConnm
// and continue processing the queue on the next call.
}
- pfrom.vRecvGetData.erase(pfrom.vRecvGetData.begin(), it);
+ peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
if (!vNotFound.empty()) {
// Let the peer know that we didn't find what it asked for, so it doesn't
@@ -2270,12 +2263,12 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
+ PeerRef peer = GetPeerRef(pfrom.GetId());
+ if (peer == nullptr) return;
if (msg_type == NetMsgType::VERSION) {
- // Each connection can only send one version message
- if (pfrom.nVersion != 0)
- {
- Misbehaving(pfrom.GetId(), 1, "redundant version message");
+ if (pfrom.nVersion != 0) {
+ LogPrint(BCLog::NET, "redundant version message from peer=%d\n", pfrom.GetId());
return;
}
@@ -2335,9 +2328,9 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
SeenLocal(addrMe);
}
- // Be shy and don't send version until we hear
- if (pfrom.IsInboundConn())
- PushNodeVersion(pfrom, m_connman, GetAdjustedTime());
+ // Inbound peers send us their version message when they connect.
+ // We send our version message in response.
+ if (pfrom.IsInboundConn()) PushNodeVersion(pfrom, GetAdjustedTime());
// Change version
const int greatest_common_version = std::min(nVersion, PROTOCOL_VERSION);
@@ -2350,10 +2343,16 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::WTXIDRELAY));
}
- m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
-
// Signal ADDRv2 support (BIP155).
- m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
+ if (greatest_common_version >= 70016) {
+ // BIP155 defines addrv2 and sendaddrv2 for all protocol versions, but some
+ // implementations reject messages they don't know. As a courtesy, don't send
+ // it to nodes with a version before 70016, as no software is known to support
+ // BIP155 that doesn't announce at least that protocol version number.
+ m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
+ }
+
+ m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
pfrom.nServices = nServices;
pfrom.SetAddrLocal(addrMe);
@@ -2395,14 +2394,8 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// empty and no one will know who we are, so these mechanisms are
// important to help us connect to the network.
//
- // We also update the addrman to record connection success for
- // these peers (which include OUTBOUND_FULL_RELAY and FEELER
- // connections) so that addrman will have an up-to-date notion of
- // which peers are online and available.
- //
- // We skip these operations for BLOCK_RELAY peers to avoid
- // potentially leaking information about our BLOCK_RELAY
- // connections via the addrman or address relay.
+ // We skip this for BLOCK_RELAY peers to avoid potentially leaking
+ // information about our BLOCK_RELAY connections via address relay.
if (fListen && !::ChainstateActive().IsInitialBlockDownload())
{
CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices());
@@ -2421,9 +2414,23 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// Get recent addresses
m_connman.PushMessage(&pfrom, CNetMsgMaker(greatest_common_version).Make(NetMsgType::GETADDR));
pfrom.fGetAddr = true;
+ }
- // Moves address from New to Tried table in Addrman, resolves
- // tried-table collisions, etc.
+ if (!pfrom.IsInboundConn()) {
+ // For non-inbound connections, we update the addrman to record
+ // connection success so that addrman will have an up-to-date
+ // notion of which peers are online and available.
+ //
+ // While we strive to not leak information about block-relay-only
+ // connections via the addrman, not moving an address to the tried
+ // table is also potentially detrimental because new-table entries
+ // are subject to eviction in the event of addrman collisions. We
+ // mitigate the information-leak by never calling
+ // CAddrMan::Connected() on block-relay-only peers; see
+ // FinalizeNode().
+ //
+ // This moves an address from New to Tried table in Addrman,
+ // resolves tried-table collisions, etc.
m_connman.MarkAddressGood(pfrom.addr);
}
@@ -2455,7 +2462,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
if (pfrom.nVersion == 0) {
// Must have a version message before anything else
- Misbehaving(pfrom.GetId(), 1, "non-version message before version handshake");
+ LogPrint(BCLog::NET, "non-version message before version handshake. Message \"%s\" from peer=%d\n", SanitizeString(msg_type), pfrom.GetId());
return;
}
@@ -2466,13 +2473,10 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
if (pfrom.fSuccessfullyConnected) return;
if (!pfrom.IsInboundConn()) {
- // Mark this node as currently connected, so we update its timestamp later.
- LOCK(cs_main);
- State(pfrom.GetId())->fCurrentlyConnected = true;
LogPrintf("New outbound peer connected: version: %d, blocks=%d, peer=%d%s (%s)\n",
pfrom.nVersion.load(), pfrom.nStartingHeight,
pfrom.GetId(), (fLogIPs ? strprintf(", peeraddr=%s", pfrom.addr.ToString()) : ""),
- pfrom.m_tx_relay == nullptr ? "block-relay" : "full-relay");
+ pfrom.IsBlockOnlyConn() ? "block-relay" : "full-relay");
}
if (pfrom.GetCommonVersion() >= SENDHEADERS_VERSION) {
@@ -2499,8 +2503,41 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
- // Feature negotiation of wtxidrelay should happen between VERSION and
- // VERACK, to avoid relay problems from switching after a connection is up
+ if (msg_type == NetMsgType::SENDHEADERS) {
+ LOCK(cs_main);
+ State(pfrom.GetId())->fPreferHeaders = true;
+ return;
+ }
+
+ if (msg_type == NetMsgType::SENDCMPCT) {
+ bool fAnnounceUsingCMPCTBLOCK = false;
+ uint64_t nCMPCTBLOCKVersion = 0;
+ vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
+ if (nCMPCTBLOCKVersion == 1 || ((pfrom.GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) {
+ LOCK(cs_main);
+ // fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness)
+ if (!State(pfrom.GetId())->fProvidesHeaderAndIDs) {
+ State(pfrom.GetId())->fProvidesHeaderAndIDs = true;
+ State(pfrom.GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
+ }
+ if (State(pfrom.GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) { // ignore later version announces
+ State(pfrom.GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
+ // save whether peer selects us as BIP152 high-bandwidth peer
+ // (receiving sendcmpct(1) signals high-bandwidth, sendcmpct(0) low-bandwidth)
+ pfrom.m_bip152_highbandwidth_from = fAnnounceUsingCMPCTBLOCK;
+ }
+ if (!State(pfrom.GetId())->fSupportsDesiredCmpctVersion) {
+ if (pfrom.GetLocalServices() & NODE_WITNESS)
+ State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
+ else
+ State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
+ }
+ }
+ return;
+ }
+
+ // Feature negotiation of wtxidrelay must happen between VERSION and VERACK
+ // to avoid relay problems from switching after a connection is up.
if (msg_type == NetMsgType::WTXIDRELAY) {
if (pfrom.fSuccessfullyConnected) {
// Disconnect peers that send wtxidrelay message after VERACK; this
@@ -2518,6 +2555,17 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
+ if (msg_type == NetMsgType::SENDADDRV2) {
+ if (pfrom.fSuccessfullyConnected) {
+ // Disconnect peers that send SENDADDRV2 message after VERACK; this
+ // must be negotiated between VERSION and VERACK.
+ pfrom.fDisconnect = true;
+ return;
+ }
+ pfrom.m_wants_addrv2 = true;
+ return;
+ }
+
if (!pfrom.fSuccessfullyConnected) {
LogPrint(BCLog::NET, "Unsupported message \"%s\" prior to verack from peer=%d\n", SanitizeString(msg_type), pfrom.GetId());
return;
@@ -2571,7 +2619,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
if (addr.nTime > nSince && !pfrom.fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
{
// Relay to a limited number of other nodes
- RelayAddress(addr, fReachable, m_connman);
+ RelayAddress(pfrom, addr, fReachable, m_connman);
}
// Do not store addresses outside our network
if (fReachable)
@@ -2585,40 +2633,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
- if (msg_type == NetMsgType::SENDADDRV2) {
- pfrom.m_wants_addrv2 = true;
- return;
- }
-
- if (msg_type == NetMsgType::SENDHEADERS) {
- LOCK(cs_main);
- State(pfrom.GetId())->fPreferHeaders = true;
- return;
- }
-
- if (msg_type == NetMsgType::SENDCMPCT) {
- bool fAnnounceUsingCMPCTBLOCK = false;
- uint64_t nCMPCTBLOCKVersion = 0;
- vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
- if (nCMPCTBLOCKVersion == 1 || ((pfrom.GetLocalServices() & NODE_WITNESS) && nCMPCTBLOCKVersion == 2)) {
- LOCK(cs_main);
- // fProvidesHeaderAndIDs is used to "lock in" version of compact blocks we send (fWantsCmpctWitness)
- if (!State(pfrom.GetId())->fProvidesHeaderAndIDs) {
- State(pfrom.GetId())->fProvidesHeaderAndIDs = true;
- State(pfrom.GetId())->fWantsCmpctWitness = nCMPCTBLOCKVersion == 2;
- }
- if (State(pfrom.GetId())->fWantsCmpctWitness == (nCMPCTBLOCKVersion == 2)) // ignore later version announces
- State(pfrom.GetId())->fPreferHeaderAndIDs = fAnnounceUsingCMPCTBLOCK;
- if (!State(pfrom.GetId())->fSupportsDesiredCmpctVersion) {
- if (pfrom.GetLocalServices() & NODE_WITNESS)
- State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 2);
- else
- State(pfrom.GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
- }
- }
- return;
- }
-
if (msg_type == NetMsgType::INV) {
std::vector<CInv> vInv;
vRecv >> vInv;
@@ -2630,7 +2644,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// We won't accept tx inv's if we're in blocks-only mode, or this is a
// block-relay-only peer
- bool fBlocksOnly = !g_relay_txes || (pfrom.m_tx_relay == nullptr);
+ bool fBlocksOnly = m_ignore_incoming_txs || (pfrom.m_tx_relay == nullptr);
// Allow peers with relay permission to send data other than blocks in blocks only mode
if (pfrom.HasPermission(PF_RELAY)) {
@@ -2708,8 +2722,12 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom.GetId());
}
- pfrom.vRecvGetData.insert(pfrom.vRecvGetData.end(), vInv.begin(), vInv.end());
- ProcessGetData(pfrom, m_chainparams, m_connman, m_mempool, interruptMsgProc);
+ {
+ LOCK(peer->m_getdata_requests_mutex);
+ peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
+ ProcessGetData(pfrom, *peer, m_chainparams, m_connman, m_mempool, interruptMsgProc);
+ }
+
return;
}
@@ -2797,36 +2815,38 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
return;
}
- LOCK(cs_main);
+ {
+ LOCK(cs_main);
- const CBlockIndex* pindex = LookupBlockIndex(req.blockhash);
- if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) {
- LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom.GetId());
- return;
- }
+ const CBlockIndex* pindex = LookupBlockIndex(req.blockhash);
+ if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) {
+ LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", pfrom.GetId());
+ return;
+ }
- if (pindex->nHeight < ::ChainActive().Height() - MAX_BLOCKTXN_DEPTH) {
- // If an older block is requested (should never happen in practice,
- // but can happen in tests) send a block response instead of a
- // blocktxn response. Sending a full block response instead of a
- // small blocktxn response is preferable in the case where a peer
- // might maliciously send lots of getblocktxn requests to trigger
- // expensive disk reads, because it will require the peer to
- // actually receive all the data read from disk over the network.
- LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
- CInv inv;
- inv.type = State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK;
- inv.hash = req.blockhash;
- pfrom.vRecvGetData.push_back(inv);
- // The message processing loop will go around again (without pausing) and we'll respond then (without cs_main)
- return;
- }
+ if (pindex->nHeight >= ::ChainActive().Height() - MAX_BLOCKTXN_DEPTH) {
+ CBlock block;
+ bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
+ assert(ret);
- CBlock block;
- bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus());
- assert(ret);
+ SendBlockTransactions(pfrom, block, req);
+ return;
+ }
+ }
- SendBlockTransactions(pfrom, block, req);
+ // If an older block is requested (should never happen in practice,
+ // but can happen in tests) send a block response instead of a
+ // blocktxn response. Sending a full block response instead of a
+ // small blocktxn response is preferable in the case where a peer
+ // might maliciously send lots of getblocktxn requests to trigger
+ // expensive disk reads, because it will require the peer to
+ // actually receive all the data read from disk over the network.
+ LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep\n", pfrom.GetId(), MAX_BLOCKTXN_DEPTH);
+ CInv inv;
+ WITH_LOCK(cs_main, inv.type = State(pfrom.GetId())->fWantsCmpctWitness ? MSG_WITNESS_BLOCK : MSG_BLOCK);
+ inv.hash = req.blockhash;
+ WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
+ // The message processing loop will go around again (without pausing) and we'll respond then
return;
}
@@ -2901,7 +2921,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// Stop processing the transaction early if
// 1) We are in blocks only mode and peer has no relay permission
// 2) This peer is a block-relay-only peer
- if ((!g_relay_txes && !pfrom.HasPermission(PF_RELAY)) || (pfrom.m_tx_relay == nullptr))
+ if ((m_ignore_incoming_txs && !pfrom.HasPermission(PF_RELAY)) || (pfrom.m_tx_relay == nullptr))
{
LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom.GetId());
pfrom.fDisconnect = true;
@@ -2930,13 +2950,9 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
pfrom.AddKnownTx(txid);
}
- TxValidationState state;
-
m_txrequest.ReceivedResponse(pfrom.GetId(), txid);
if (tx.HasWitness()) m_txrequest.ReceivedResponse(pfrom.GetId(), wtxid);
- std::list<CTransactionRef> lRemovedTxn;
-
// We do the AlreadyHaveTx() check using wtxid, rather than txid - in the
// absence of witness malleation, this is strictly better, because the
// recent rejects filter may contain the wtxid but rarely contains
@@ -2949,8 +2965,25 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
// already; and an adversary can already relay us old transactions
// (older than our recency filter) if trying to DoS us, without any need
// for witness malleation.
- if (!AlreadyHaveTx(GenTxid(/* is_wtxid=*/true, wtxid), m_mempool) &&
- AcceptToMemoryPool(m_mempool, state, ptx, &lRemovedTxn, false /* bypass_limits */)) {
+ if (AlreadyHaveTx(GenTxid(/* is_wtxid=*/true, wtxid), m_mempool)) {
+ if (pfrom.HasPermission(PF_FORCERELAY)) {
+ // Always relay transactions received from peers with forcerelay
+ // permission, even if they were already in the mempool, allowing
+ // the node to function as a gateway for nodes hidden behind it.
+ if (!m_mempool.exists(tx.GetHash())) {
+ LogPrintf("Not relaying non-mempool transaction %s from forcerelay peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
+ } else {
+ LogPrintf("Force relaying tx %s from peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
+ RelayTransaction(tx.GetHash(), tx.GetWitnessHash(), m_connman);
+ }
+ }
+ return;
+ }
+
+ TxValidationState state;
+ std::list<CTransactionRef> lRemovedTxn;
+
+ if (AcceptToMemoryPool(m_mempool, state, ptx, &lRemovedTxn, false /* bypass_limits */)) {
m_mempool.check(&::ChainstateActive().CoinsTip());
// As this version of the transaction was acceptable, we can forget about any
// requests for it.
@@ -2961,7 +2994,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
auto it_by_prev = mapOrphanTransactionsByPrev.find(COutPoint(txid, i));
if (it_by_prev != mapOrphanTransactionsByPrev.end()) {
for (const auto& elem : it_by_prev->second) {
- pfrom.orphan_work_set.insert(elem->first);
+ peer->m_orphan_work_set.insert(elem->first);
}
}
}
@@ -2978,7 +3011,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
}
// Recursively process any orphan transactions that depended on this one
- ProcessOrphanTx(pfrom.orphan_work_set);
+ ProcessOrphanTx(peer->m_orphan_work_set);
}
else if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS)
{
@@ -3072,19 +3105,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
AddToCompactExtraTransactions(ptx);
}
}
-
- if (pfrom.HasPermission(PF_FORCERELAY)) {
- // Always relay transactions received from peers with forcerelay permission, even
- // if they were already in the mempool,
- // allowing the node to function as a gateway for
- // nodes hidden behind it.
- if (!m_mempool.exists(tx.GetHash())) {
- LogPrintf("Not relaying non-mempool transaction %s from forcerelay peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
- } else {
- LogPrintf("Force relaying tx %s from peer=%d\n", tx.GetHash().ToString(), pfrom.GetId());
- RelayTransaction(tx.GetHash(), tx.GetWitnessHash(), m_connman);
- }
- }
}
// If a tx has been detected by recentRejects, we will have reached
@@ -3763,7 +3783,7 @@ bool PeerManager::MaybeDiscourageAndDisconnect(CNode& pnode)
}
// Normal case: Disconnect the peer and discourage all nodes sharing the address
- LogPrintf("Disconnecting and discouraging peer %d!\n", peer_id);
+ LogPrint(BCLog::NET, "Disconnecting and discouraging peer %d!\n", peer_id);
if (m_banman) m_banman->Discourage(pnode.addr);
m_connman.DisconnectNode(pnode.addr);
return true;
@@ -3773,21 +3793,37 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgP
{
bool fMoreWork = false;
- if (!pfrom->vRecvGetData.empty())
- ProcessGetData(*pfrom, m_chainparams, m_connman, m_mempool, interruptMsgProc);
+ PeerRef peer = GetPeerRef(pfrom->GetId());
+ if (peer == nullptr) return false;
+
+ {
+ LOCK(peer->m_getdata_requests_mutex);
+ if (!peer->m_getdata_requests.empty()) {
+ ProcessGetData(*pfrom, *peer, m_chainparams, m_connman, m_mempool, interruptMsgProc);
+ }
+ }
- if (!pfrom->orphan_work_set.empty()) {
+ {
LOCK2(cs_main, g_cs_orphans);
- ProcessOrphanTx(pfrom->orphan_work_set);
+ if (!peer->m_orphan_work_set.empty()) {
+ ProcessOrphanTx(peer->m_orphan_work_set);
+ }
}
if (pfrom->fDisconnect)
return false;
// this maintains the order of responses
- // and prevents vRecvGetData to grow unbounded
- if (!pfrom->vRecvGetData.empty()) return true;
- if (!pfrom->orphan_work_set.empty()) return true;
+ // and prevents m_getdata_requests to grow unbounded
+ {
+ LOCK(peer->m_getdata_requests_mutex);
+ if (!peer->m_getdata_requests.empty()) return true;
+ }
+
+ {
+ LOCK(g_cs_orphans);
+ if (!peer->m_orphan_work_set.empty()) return true;
+ }
// Don't bother if send buffer is too full to respond anyway
if (pfrom->fPauseSend)
@@ -3814,10 +3850,11 @@ bool PeerManager::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgP
try {
ProcessMessage(*pfrom, msg_type, msg.m_recv, msg.m_time, interruptMsgProc);
- if (interruptMsgProc)
- return false;
- if (!pfrom->vRecvGetData.empty())
- fMoreWork = true;
+ if (interruptMsgProc) return false;
+ {
+ LOCK(peer->m_getdata_requests_mutex);
+ if (!peer->m_getdata_requests.empty()) fMoreWork = true;
+ }
} catch (const std::exception& e) {
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' (%s) caught\n", __func__, SanitizeString(msg_type), nMessageSize, e.what(), typeid(e).name());
} catch (...) {
@@ -3882,11 +3919,54 @@ void PeerManager::ConsiderEviction(CNode& pto, int64_t time_in_seconds)
void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds)
{
- // Check whether we have too many outbound peers
- int extra_peers = m_connman.GetExtraOutboundCount();
- if (extra_peers > 0) {
- // If we have more outbound peers than we target, disconnect one.
- // Pick the outbound peer that least recently announced
+ // If we have any extra block-relay-only peers, disconnect the youngest unless
+ // it's given us a block -- in which case, compare with the second-youngest, and
+ // out of those two, disconnect the peer who least recently gave us a block.
+ // The youngest block-relay-only peer would be the extra peer we connected
+ // to temporarily in order to sync our tip; see net.cpp.
+ // Note that we use higher nodeid as a measure for most recent connection.
+ if (m_connman.GetExtraBlockRelayCount() > 0) {
+ std::pair<NodeId, int64_t> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
+
+ m_connman.ForEachNode([&](CNode* pnode) {
+ if (!pnode->IsBlockOnlyConn() || pnode->fDisconnect) return;
+ if (pnode->GetId() > youngest_peer.first) {
+ next_youngest_peer = youngest_peer;
+ youngest_peer.first = pnode->GetId();
+ youngest_peer.second = pnode->nLastBlockTime;
+ }
+ });
+ NodeId to_disconnect = youngest_peer.first;
+ if (youngest_peer.second > next_youngest_peer.second) {
+ // Our newest block-relay-only peer gave us a block more recently;
+ // disconnect our second youngest.
+ to_disconnect = next_youngest_peer.first;
+ }
+ m_connman.ForNode(to_disconnect, [&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
+ AssertLockHeld(::cs_main);
+ // Make sure we're not getting a block right now, and that
+ // we've been connected long enough for this eviction to happen
+ // at all.
+ // Note that we only request blocks from a peer if we learn of a
+ // valid headers chain with at least as much work as our tip.
+ CNodeState *node_state = State(pnode->GetId());
+ if (node_state == nullptr ||
+ (time_in_seconds - pnode->nTimeConnected >= MINIMUM_CONNECT_TIME && node_state->nBlocksInFlight == 0)) {
+ pnode->fDisconnect = true;
+ LogPrint(BCLog::NET, "disconnecting extra block-relay-only peer=%d (last block received at time %d)\n", pnode->GetId(), pnode->nLastBlockTime);
+ return true;
+ } else {
+ LogPrint(BCLog::NET, "keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
+ pnode->GetId(), pnode->nTimeConnected, node_state->nBlocksInFlight);
+ }
+ return false;
+ });
+ }
+
+ // Check whether we have too many OUTBOUND_FULL_RELAY peers
+ if (m_connman.GetExtraFullOutboundCount() > 0) {
+ // If we have more OUTBOUND_FULL_RELAY peers than we target, disconnect one.
+ // Pick the OUTBOUND_FULL_RELAY peer that least recently announced
// us a new block, with ties broken by choosing the more recent
// connection (higher node id)
NodeId worst_peer = -1;
@@ -3895,14 +3975,13 @@ void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds)
m_connman.ForEachNode([&](CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
AssertLockHeld(::cs_main);
- // Ignore non-outbound peers, or nodes marked for disconnect already
- if (!pnode->IsOutboundOrBlockRelayConn() || pnode->fDisconnect) return;
+ // Only consider OUTBOUND_FULL_RELAY peers that are not already
+ // marked for disconnection
+ if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
CNodeState *state = State(pnode->GetId());
if (state == nullptr) return; // shouldn't be possible, but just in case
// Don't evict our protected peers
if (state->m_chain_sync.m_protect) return;
- // Don't evict our block-relay-only peers.
- if (pnode->m_tx_relay == nullptr) return;
if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
worst_peer = pnode->GetId();
oldest_block_announcement = state->m_last_block_announcement;
@@ -3958,6 +4037,11 @@ void PeerManager::CheckForStaleTipAndEvictPeers()
}
m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL;
}
+
+ if (!m_initial_sync_finished && CanDirectFetch(m_chainparams.GetConsensus())) {
+ m_connman.StartExtraBlockRelayPeers();
+ m_initial_sync_finished = true;
+ }
}
namespace {
@@ -4034,6 +4118,15 @@ bool PeerManager::SendMessages(CNode* pto)
auto current_time = GetTime<std::chrono::microseconds>();
if (pto->RelayAddrsWithConn() && !::ChainstateActive().IsInitialBlockDownload() && pto->m_next_local_addr_send < current_time) {
+ // If we've sent before, clear the bloom filter for the peer, so that our
+ // self-announcement will actually go out.
+ // This might be unnecessary if the bloom filter has already rolled
+ // over since our last self-announcement, but there is only a small
+ // bandwidth cost that we can incur by doing this (which happens
+ // once a day on average).
+ if (pto->m_next_local_addr_send != 0us) {
+ pto->m_addr_known->reset();
+ }
AdvertiseLocal(pto);
pto->m_next_local_addr_send = PoissonNextSend(current_time, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
diff --git a/src/net_processing.h b/src/net_processing.h
index 578660355a..12a4e9c38f 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -32,10 +32,52 @@ static const bool DEFAULT_PEERBLOCKFILTERS = false;
/** Threshold for marking a node to be discouraged, e.g. disconnected and added to the discouragement filter. */
static const int DISCOURAGEMENT_THRESHOLD{100};
+struct CNodeStateStats {
+ int m_misbehavior_score = 0;
+ int nSyncHeight = -1;
+ int nCommonHeight = -1;
+ std::vector<int> vHeightInFlight;
+};
+
+/**
+ * Data structure for an individual peer. This struct is not protected by
+ * cs_main since it does not contain validation-critical data.
+ *
+ * Memory is owned by shared pointers and this object is destructed when
+ * the refcount drops to zero.
+ *
+ * TODO: move most members from CNodeState to this structure.
+ * TODO: move remaining application-layer data members from CNode to this structure.
+ */
+struct Peer {
+ /** Same id as the CNode object for this peer */
+ const NodeId m_id{0};
+
+ /** Protects misbehavior data members */
+ Mutex m_misbehavior_mutex;
+ /** Accumulated misbehavior score for this peer */
+ int m_misbehavior_score GUARDED_BY(m_misbehavior_mutex){0};
+ /** Whether this peer should be disconnected and marked as discouraged (unless it has the noban permission). */
+ bool m_should_discourage GUARDED_BY(m_misbehavior_mutex){false};
+
+ /** Set of txids to reconsider once their parent transactions have been accepted **/
+ std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
+
+ /** 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);
+
+ explicit Peer(NodeId id) : m_id(id) {}
+};
+
+using PeerRef = std::shared_ptr<Peer>;
+
class PeerManager final : public CValidationInterface, public NetEventsInterface {
public:
PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
- CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool);
+ CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool,
+ bool ignore_incoming_txs);
/**
* Overridden from CValidationInterface.
@@ -58,7 +100,7 @@ public:
/** Initialize a peer by adding it to mapNodeState and pushing a message requesting its version */
void InitializeNode(CNode* pnode) override;
/** Handle removal of a peer by updating various state and removing it from mapNodeState */
- void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) override;
+ void FinalizeNode(const CNode& node, bool& fUpdateConnectionTime) override;
/**
* Process protocol messages received from a given node
*
@@ -94,7 +136,21 @@ public:
*/
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message);
+ /** Get statistics from node state */
+ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats);
+
+ /** Whether this node ignores txs received over p2p. */
+ bool IgnoresIncomingTxs() {return m_ignore_incoming_txs;};
+
private:
+ /** Get a shared pointer to the Peer object.
+ * May return an empty shared_ptr if the Peer object can't be found. */
+ PeerRef GetPeerRef(NodeId id) const;
+
+ /** Get a shared pointer to the Peer object and remove it from m_peer_map.
+ * May return an empty shared_ptr if the Peer object can't be found. */
+ PeerRef RemovePeer(NodeId id);
+
/**
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
*
@@ -134,6 +190,9 @@ private:
void AddTxAnnouncement(const CNode& node, const GenTxid& gtxid, std::chrono::microseconds current_time)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
+ /** Send a version message to a peer */
+ void PushNodeVersion(CNode& pnode, int64_t nTime);
+
const CChainParams& m_chainparams;
CConnman& m_connman;
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
@@ -143,17 +202,24 @@ private:
TxRequestTracker m_txrequest GUARDED_BY(::cs_main);
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
-};
-struct CNodeStateStats {
- int m_misbehavior_score = 0;
- int nSyncHeight = -1;
- int nCommonHeight = -1;
- std::vector<int> vHeightInFlight;
-};
+ //* Whether this node is running in blocks only mode */
+ const bool m_ignore_incoming_txs;
+
+ /** Whether we've completed initial sync yet, for determining when to turn
+ * on extra block-relay-only peers. */
+ bool m_initial_sync_finished{false};
-/** Get statistics from node state */
-bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
+ /** Protects m_peer_map */
+ mutable Mutex m_peer_mutex;
+ /**
+ * Map of all Peer objects, keyed by peer id. This map is protected
+ * by the m_peer_mutex. Once a shared pointer reference is
+ * taken, the lock may be released. Individual fields are protected by
+ * their own locks.
+ */
+ std::map<NodeId, PeerRef> m_peer_map GUARDED_BY(m_peer_mutex);
+};
/** Relay transaction to every node */
void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index c0193fa2e9..b1f9d32d34 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -255,10 +255,14 @@ bool CNetAddr::SetSpecial(const std::string& str)
Span<const uint8_t> input_checksum{input.data() + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN};
Span<const uint8_t> input_version{input.data() + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, sizeof(torv3::VERSION)};
+ if (input_version != torv3::VERSION) {
+ return false;
+ }
+
uint8_t calculated_checksum[torv3::CHECKSUM_LEN];
torv3::Checksum(input_pubkey, calculated_checksum);
- if (input_checksum != calculated_checksum || input_version != torv3::VERSION) {
+ if (input_checksum != calculated_checksum) {
return false;
}
@@ -433,6 +437,11 @@ bool CNetAddr::IsValid() const
return false;
}
+ // CJDNS addresses always start with 0xfc
+ if (IsCJDNS() && (m_addr[0] != 0xFC)) {
+ return false;
+ }
+
// documentation IPv6 address
if (IsRFC3849())
return false;
diff --git a/src/netaddress.h b/src/netaddress.h
index f35b01d202..29b2eaafeb 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -29,7 +29,7 @@
* Make sure that this does not collide with any of the values in `version.h`
* or with `SERIALIZE_TRANSACTION_NO_WITNESS`.
*/
-static const int ADDRV2_FORMAT = 0x20000000;
+static constexpr int ADDRV2_FORMAT = 0x20000000;
/**
* A network type.
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 0273839017..264029d8a2 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -52,14 +52,20 @@ enum Network ParseNetwork(const std::string& net_in) {
return NET_UNROUTABLE;
}
-std::string GetNetworkName(enum Network net) {
- switch(net)
- {
+std::string GetNetworkName(enum Network net)
+{
+ switch (net) {
+ case NET_UNROUTABLE: return "unroutable";
case NET_IPV4: return "ipv4";
case NET_IPV6: return "ipv6";
case NET_ONION: return "onion";
- default: return "";
- }
+ case NET_I2P: return "i2p";
+ case NET_CJDNS: return "cjdns";
+ case NET_INTERNAL: return "internal";
+ case NET_MAX: assert(false);
+ } // no default case, so the compiler can warn about missing cases
+
+ assert(false);
}
bool static LookupIntern(const std::string& name, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
diff --git a/src/node/coinstats.cpp b/src/node/coinstats.cpp
index fb46ea1731..02e50c4dbe 100644
--- a/src/node/coinstats.cpp
+++ b/src/node/coinstats.cpp
@@ -112,7 +112,7 @@ bool GetUTXOStats(CCoinsView* view, CCoinsStats& stats, CoinStatsHashType hash_t
}
// The legacy hash serializes the hashBlock
-static void PrepareHash(CHashWriter& ss, CCoinsStats& stats)
+static void PrepareHash(CHashWriter& ss, const CCoinsStats& stats)
{
ss << stats.hashBlock;
}
diff --git a/src/node/context.cpp b/src/node/context.cpp
index 49d0c37235..958221a913 100644
--- a/src/node/context.cpp
+++ b/src/node/context.cpp
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <net.h>
#include <net_processing.h>
+#include <policy/fees.h>
#include <scheduler.h>
#include <txmempool.h>
diff --git a/src/node/context.h b/src/node/context.h
index 3228831ed1..9b611bf8f5 100644
--- a/src/node/context.h
+++ b/src/node/context.h
@@ -12,6 +12,7 @@
class ArgsManager;
class BanMan;
+class CBlockPolicyEstimator;
class CConnman;
class CScheduler;
class CTxMemPool;
@@ -36,6 +37,7 @@ class WalletClient;
struct NodeContext {
std::unique_ptr<CConnman> connman;
std::unique_ptr<CTxMemPool> mempool;
+ std::unique_ptr<CBlockPolicyEstimator> fee_estimator;
std::unique_ptr<PeerManager> peerman;
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::unique_ptr<BanMan> banman;
diff --git a/src/interfaces/chain.cpp b/src/node/interfaces.cpp
index 4c5ebe66fc..317a5c7cbe 100644
--- a/src/interfaces/chain.cpp
+++ b/src/node/interfaces.cpp
@@ -2,18 +2,25 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <interfaces/chain.h>
-
+#include <addrdb.h>
+#include <banman.h>
+#include <boost/signals2/signal.hpp>
#include <chain.h>
#include <chainparams.h>
+#include <init.h>
+#include <interfaces/chain.h>
#include <interfaces/handler.h>
+#include <interfaces/node.h>
#include <interfaces/wallet.h>
#include <net.h>
#include <net_processing.h>
+#include <netaddress.h>
+#include <netbase.h>
#include <node/coin.h>
#include <node/context.h>
#include <node/transaction.h>
#include <node/ui_interface.h>
+#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -23,22 +30,282 @@
#include <rpc/protocol.h>
#include <rpc/server.h>
#include <shutdown.h>
+#include <support/allocators/secure.h>
#include <sync.h>
#include <timedata.h>
#include <txmempool.h>
#include <uint256.h>
#include <univalue.h>
+#include <util/check.h>
+#include <util/ref.h>
#include <util/system.h>
+#include <util/translation.h>
#include <validation.h>
#include <validationinterface.h>
+#include <warnings.h>
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
#include <memory>
#include <utility>
-namespace interfaces {
+using interfaces::BlockTip;
+using interfaces::Chain;
+using interfaces::FoundBlock;
+using interfaces::Handler;
+using interfaces::MakeHandler;
+using interfaces::Node;
+using interfaces::WalletClient;
+
+namespace node {
namespace {
+class NodeImpl : public Node
+{
+public:
+ explicit NodeImpl(NodeContext* context) { setContext(context); }
+ void initLogging() override { InitLogging(*Assert(m_context->args)); }
+ void initParameterInteraction() override { InitParameterInteraction(*Assert(m_context->args)); }
+ bilingual_str getWarnings() override { return GetWarnings(true); }
+ uint32_t getLogCategories() override { return LogInstance().GetCategoryMask(); }
+ bool baseInitialize() override
+ {
+ return AppInitBasicSetup(gArgs) && AppInitParameterInteraction(gArgs) && AppInitSanityChecks() &&
+ AppInitLockDataDirectory() && AppInitInterfaces(*m_context);
+ }
+ bool appInitMain(interfaces::BlockAndHeaderTipInfo* tip_info) override
+ {
+ return AppInitMain(m_context_ref, *m_context, tip_info);
+ }
+ void appShutdown() override
+ {
+ Interrupt(*m_context);
+ Shutdown(*m_context);
+ }
+ void startShutdown() override
+ {
+ StartShutdown();
+ // Stop RPC for clean shutdown if any of waitfor* commands is executed.
+ if (gArgs.GetBoolArg("-server", false)) {
+ InterruptRPC();
+ StopRPC();
+ }
+ }
+ bool shutdownRequested() override { return ShutdownRequested(); }
+ void mapPort(bool use_upnp) override
+ {
+ if (use_upnp) {
+ StartMapPort();
+ } else {
+ InterruptMapPort();
+ StopMapPort();
+ }
+ }
+ bool getProxy(Network net, proxyType& proxy_info) override { return GetProxy(net, proxy_info); }
+ size_t getNodeCount(CConnman::NumConnections flags) override
+ {
+ return m_context->connman ? m_context->connman->GetNodeCount(flags) : 0;
+ }
+ bool getNodesStats(NodesStats& stats) override
+ {
+ stats.clear();
-bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock)
+ if (m_context->connman) {
+ std::vector<CNodeStats> stats_temp;
+ m_context->connman->GetNodeStats(stats_temp);
+
+ stats.reserve(stats_temp.size());
+ for (auto& node_stats_temp : stats_temp) {
+ stats.emplace_back(std::move(node_stats_temp), false, CNodeStateStats());
+ }
+
+ // Try to retrieve the CNodeStateStats for each node.
+ if (m_context->peerman) {
+ TRY_LOCK(::cs_main, lockMain);
+ if (lockMain) {
+ for (auto& node_stats : stats) {
+ std::get<1>(node_stats) =
+ m_context->peerman->GetNodeStateStats(std::get<0>(node_stats).nodeid, std::get<2>(node_stats));
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ bool getBanned(banmap_t& banmap) override
+ {
+ if (m_context->banman) {
+ m_context->banman->GetBanned(banmap);
+ return true;
+ }
+ return false;
+ }
+ bool ban(const CNetAddr& net_addr, int64_t ban_time_offset) override
+ {
+ if (m_context->banman) {
+ m_context->banman->Ban(net_addr, ban_time_offset);
+ return true;
+ }
+ return false;
+ }
+ bool unban(const CSubNet& ip) override
+ {
+ if (m_context->banman) {
+ m_context->banman->Unban(ip);
+ return true;
+ }
+ return false;
+ }
+ bool disconnectByAddress(const CNetAddr& net_addr) override
+ {
+ if (m_context->connman) {
+ return m_context->connman->DisconnectNode(net_addr);
+ }
+ return false;
+ }
+ bool disconnectById(NodeId id) override
+ {
+ if (m_context->connman) {
+ return m_context->connman->DisconnectNode(id);
+ }
+ return false;
+ }
+ int64_t getTotalBytesRecv() override { return m_context->connman ? m_context->connman->GetTotalBytesRecv() : 0; }
+ int64_t getTotalBytesSent() override { return m_context->connman ? m_context->connman->GetTotalBytesSent() : 0; }
+ size_t getMempoolSize() override { return m_context->mempool ? m_context->mempool->size() : 0; }
+ size_t getMempoolDynamicUsage() override { return m_context->mempool ? m_context->mempool->DynamicMemoryUsage() : 0; }
+ bool getHeaderTip(int& height, int64_t& block_time) override
+ {
+ LOCK(::cs_main);
+ if (::pindexBestHeader) {
+ height = ::pindexBestHeader->nHeight;
+ block_time = ::pindexBestHeader->GetBlockTime();
+ return true;
+ }
+ return false;
+ }
+ int getNumBlocks() override
+ {
+ LOCK(::cs_main);
+ return ::ChainActive().Height();
+ }
+ uint256 getBestBlockHash() override
+ {
+ const CBlockIndex* tip = WITH_LOCK(::cs_main, return ::ChainActive().Tip());
+ return tip ? tip->GetBlockHash() : Params().GenesisBlock().GetHash();
+ }
+ int64_t getLastBlockTime() override
+ {
+ LOCK(::cs_main);
+ if (::ChainActive().Tip()) {
+ return ::ChainActive().Tip()->GetBlockTime();
+ }
+ return Params().GenesisBlock().GetBlockTime(); // Genesis block's time of current network
+ }
+ double getVerificationProgress() override
+ {
+ const CBlockIndex* tip;
+ {
+ LOCK(::cs_main);
+ tip = ::ChainActive().Tip();
+ }
+ return GuessVerificationProgress(Params().TxData(), tip);
+ }
+ bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); }
+ bool getReindex() override { return ::fReindex; }
+ bool getImporting() override { return ::fImporting; }
+ void setNetworkActive(bool active) override
+ {
+ if (m_context->connman) {
+ m_context->connman->SetNetworkActive(active);
+ }
+ }
+ bool getNetworkActive() override { return m_context->connman && m_context->connman->GetNetworkActive(); }
+ CFeeRate getDustRelayFee() override { return ::dustRelayFee; }
+ UniValue executeRpc(const std::string& command, const UniValue& params, const std::string& uri) override
+ {
+ JSONRPCRequest req(m_context_ref);
+ req.params = params;
+ req.strMethod = command;
+ req.URI = uri;
+ return ::tableRPC.execute(req);
+ }
+ std::vector<std::string> listRpcCommands() override { return ::tableRPC.listCommands(); }
+ void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) override { RPCSetTimerInterfaceIfUnset(iface); }
+ void rpcUnsetTimerInterface(RPCTimerInterface* iface) override { RPCUnsetTimerInterface(iface); }
+ bool getUnspentOutput(const COutPoint& output, Coin& coin) override
+ {
+ LOCK(::cs_main);
+ return ::ChainstateActive().CoinsTip().GetCoin(output, coin);
+ }
+ WalletClient& walletClient() override
+ {
+ return *Assert(m_context->wallet_client);
+ }
+ std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
+ {
+ return MakeHandler(::uiInterface.InitMessage_connect(fn));
+ }
+ std::unique_ptr<Handler> handleMessageBox(MessageBoxFn fn) override
+ {
+ return MakeHandler(::uiInterface.ThreadSafeMessageBox_connect(fn));
+ }
+ std::unique_ptr<Handler> handleQuestion(QuestionFn fn) override
+ {
+ return MakeHandler(::uiInterface.ThreadSafeQuestion_connect(fn));
+ }
+ std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) override
+ {
+ return MakeHandler(::uiInterface.ShowProgress_connect(fn));
+ }
+ std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
+ {
+ return MakeHandler(::uiInterface.NotifyNumConnectionsChanged_connect(fn));
+ }
+ std::unique_ptr<Handler> handleNotifyNetworkActiveChanged(NotifyNetworkActiveChangedFn fn) override
+ {
+ return MakeHandler(::uiInterface.NotifyNetworkActiveChanged_connect(fn));
+ }
+ std::unique_ptr<Handler> handleNotifyAlertChanged(NotifyAlertChangedFn fn) override
+ {
+ return MakeHandler(::uiInterface.NotifyAlertChanged_connect(fn));
+ }
+ std::unique_ptr<Handler> handleBannedListChanged(BannedListChangedFn fn) override
+ {
+ return MakeHandler(::uiInterface.BannedListChanged_connect(fn));
+ }
+ std::unique_ptr<Handler> handleNotifyBlockTip(NotifyBlockTipFn fn) override
+ {
+ return MakeHandler(::uiInterface.NotifyBlockTip_connect([fn](SynchronizationState sync_state, const CBlockIndex* block) {
+ fn(sync_state, BlockTip{block->nHeight, block->GetBlockTime(), block->GetBlockHash()},
+ GuessVerificationProgress(Params().TxData(), block));
+ }));
+ }
+ 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);
+ }));
+ }
+ NodeContext* context() override { return m_context; }
+ void setContext(NodeContext* context) override
+ {
+ m_context = context;
+ if (context) {
+ m_context_ref.Set(*context);
+ } else {
+ m_context_ref.Clear();
+ }
+ }
+ NodeContext* m_context{nullptr};
+ util::Ref m_context_ref;
+};
+
+bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active)
{
if (!index) return false;
if (block.m_hash) *block.m_hash = index->GetBlockHash();
@@ -46,6 +313,8 @@ bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<Rec
if (block.m_time) *block.m_time = index->GetBlockTime();
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_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);
if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
@@ -148,48 +417,33 @@ public:
Optional<int> getHeight() override
{
LOCK(::cs_main);
- int height = ::ChainActive().Height();
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ int height = active.Height();
if (height >= 0) {
return height;
}
return nullopt;
}
- Optional<int> getBlockHeight(const uint256& hash) override
- {
- LOCK(::cs_main);
- CBlockIndex* block = LookupBlockIndex(hash);
- if (block && ::ChainActive().Contains(block)) {
- return block->nHeight;
- }
- return nullopt;
- }
uint256 getBlockHash(int height) override
{
LOCK(::cs_main);
- CBlockIndex* block = ::ChainActive()[height];
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ CBlockIndex* block = active[height];
assert(block);
return block->GetBlockHash();
}
bool haveBlockOnDisk(int height) override
{
LOCK(cs_main);
- CBlockIndex* block = ::ChainActive()[height];
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ CBlockIndex* block = active[height];
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
- Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
- {
- LOCK(cs_main);
- CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
- if (block) {
- if (hash) *hash = block->GetBlockHash();
- return block->nHeight;
- }
- return nullopt;
- }
CBlockLocator getTipLocator() override
{
LOCK(cs_main);
- return ::ChainActive().GetLocator();
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return active.GetLocator();
}
bool checkFinalTx(const CTransaction& tx) override
{
@@ -199,7 +453,8 @@ public:
Optional<int> findLocatorFork(const CBlockLocator& locator) override
{
LOCK(cs_main);
- if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ if (CBlockIndex* fork = FindForkInGlobalIndex(active, locator)) {
return fork->nHeight;
}
return nullopt;
@@ -207,47 +462,45 @@ public:
bool findBlock(const uint256& hash, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- return FillBlock(LookupBlockIndex(hash), block, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return FillBlock(LookupBlockIndex(hash), block, lock, active);
}
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- return FillBlock(ChainActive().FindEarliestAtLeast(min_time, min_height), block, lock);
- }
- bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next, bool* reorg) override {
- WAIT_LOCK(cs_main, lock);
- CBlockIndex* block = ChainActive()[block_height];
- if (block && block->GetBlockHash() != block_hash) block = nullptr;
- if (reorg) *reorg = !block;
- return FillBlock(block ? ChainActive()[block_height + 1] : nullptr, next, lock);
+ const CChain& active = Assert(m_node.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 = LookupBlockIndex(block_hash)) {
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
- return FillBlock(ancestor, ancestor_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active);
}
}
- return FillBlock(nullptr, ancestor_out, lock);
+ return FillBlock(nullptr, ancestor_out, lock, active);
}
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 = LookupBlockIndex(block_hash);
const CBlockIndex* ancestor = LookupBlockIndex(ancestor_hash);
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
- return FillBlock(ancestor, ancestor_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active);
}
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 = LookupBlockIndex(block_hash1);
const CBlockIndex* block2 = LookupBlockIndex(block_hash2);
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
// Using & instead of && below to avoid short circuiting and leaving
// output uninitialized.
- return FillBlock(ancestor, ancestor_out, lock) & FillBlock(block1, block1_out, lock) & FillBlock(block2, block2_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active) & FillBlock(block1, block1_out, lock, active) & FillBlock(block2, block2_out, lock, active);
}
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
double guessVerificationProgress(const uint256& block_hash) override
@@ -327,11 +580,13 @@ public:
}
CFeeRate estimateSmartFee(int num_blocks, bool conservative, FeeCalculation* calc) override
{
- return ::feeEstimator.estimateSmartFee(num_blocks, calc, conservative);
+ if (!m_node.fee_estimator) return {};
+ return m_node.fee_estimator->estimateSmartFee(num_blocks, calc, conservative);
}
unsigned int estimateMaxBlocks() override
{
- return ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+ if (!m_node.fee_estimator) return 0;
+ return m_node.fee_estimator->HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
}
CFeeRate mempoolMinFee() override
{
@@ -365,7 +620,8 @@ public:
{
if (!old_tip.IsNull()) {
LOCK(::cs_main);
- if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ if (old_tip == active.Tip()->GetBlockHash()) return;
}
SyncWithValidationInterfaceQueue();
}
@@ -411,7 +667,9 @@ public:
NodeContext& m_node;
};
} // namespace
+} // namespace node
-std::unique_ptr<Chain> MakeChain(NodeContext& node) { return MakeUnique<ChainImpl>(node); }
-
+namespace interfaces {
+std::unique_ptr<Node> MakeNode(NodeContext* context) { return MakeUnique<node::NodeImpl>(context); }
+std::unique_ptr<Chain> MakeChain(NodeContext& context) { return MakeUnique<node::ChainImpl>(context); }
} // namespace interfaces
diff --git a/src/node/transaction.h b/src/node/transaction.h
index 6491700d44..0c016ff04e 100644
--- a/src/node/transaction.h
+++ b/src/node/transaction.h
@@ -36,6 +36,6 @@ static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10};
* @param[in] wait_callback wait until callbacks have been processed to avoid stale result due to a sequentially RPC.
* return error
*/
-NODISCARD TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback);
+[[nodiscard]] TransactionError BroadcastTransaction(NodeContext& node, CTransactionRef tx, std::string& err_string, const CAmount& max_tx_fee, bool relay, bool wait_callback);
#endif // BITCOIN_NODE_TRANSACTION_H
diff --git a/src/outputtype.h b/src/outputtype.h
index 77a16b1d05..bb7f39323b 100644
--- a/src/outputtype.h
+++ b/src/outputtype.h
@@ -22,7 +22,7 @@ enum class OutputType {
extern const std::array<OutputType, 3> OUTPUT_TYPES;
-NODISCARD bool ParseOutputType(const std::string& str, OutputType& output_type);
+[[nodiscard]] bool ParseOutputType(const std::string& str, OutputType& output_type);
const std::string& FormatOutputType(OutputType type);
/**
diff --git a/src/policy/feerate.cpp b/src/policy/feerate.cpp
index a01e259731..04e0e117a5 100644
--- a/src/policy/feerate.cpp
+++ b/src/policy/feerate.cpp
@@ -38,7 +38,7 @@ CAmount CFeeRate::GetFee(size_t nBytes_) const
std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const
{
switch (fee_estimate_mode) {
- case FeeEstimateMode::SAT_B: return strprintf("%d.%03d %s/B", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM);
- default: return strprintf("%d.%08d %s/kB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT);
+ case FeeEstimateMode::SAT_VB: return strprintf("%d.%03d %s/vB", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM);
+ default: return strprintf("%d.%08d %s/kvB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT);
}
}
diff --git a/src/policy/feerate.h b/src/policy/feerate.h
index 883940f73c..7c5660ac8a 100644
--- a/src/policy/feerate.h
+++ b/src/policy/feerate.h
@@ -19,8 +19,8 @@ enum class FeeEstimateMode {
UNSET, //!< Use default settings based on other criteria
ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates
CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
- BTC_KB, //!< Use explicit BTC/kB fee given in coin control
- SAT_B, //!< Use explicit sat/B fee given in coin control
+ BTC_KVB, //!< Use BTC/kvB fee rate unit
+ SAT_VB, //!< Use sat/vB fee rate unit
};
/**
@@ -39,7 +39,16 @@ public:
// We've previously had bugs creep in from silent double->int conversion...
static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats");
}
- /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
+ /** Constructor for a fee rate in satoshis per kvB (sat/kvB). The size in bytes must not exceed (2^63 - 1).
+ *
+ * Passing an nBytes value of COIN (1e8) returns a fee rate in satoshis per vB (sat/vB),
+ * e.g. (nFeePaid * 1e8 / 1e3) == (nFeePaid / 1e5),
+ * where 1e5 is the ratio to convert from BTC/kvB to sat/vB.
+ *
+ * @param[in] nFeePaid CAmount fee rate to construct with
+ * @param[in] nBytes size_t bytes (units) to construct with
+ * @returns fee rate
+ */
CFeeRate(const CAmount& nFeePaid, size_t nBytes);
/**
* Return the fee in satoshis for the given size in bytes.
@@ -56,7 +65,7 @@ public:
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; }
CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
- std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KB) const;
+ std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::BTC_KVB) const;
SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); }
};
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 0f31093dbb..cfa4cf8421 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -6,10 +6,14 @@
#include <policy/fees.h>
#include <clientversion.h>
+#include <fs.h>
+#include <logging.h>
#include <streams.h>
#include <txmempool.h>
#include <util/system.h>
+static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
+
static constexpr double INF_FEERATE = 1e99;
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) {
@@ -489,6 +493,7 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
{
static_assert(MIN_BUCKET_FEERATE > 0, "Min feerate must be nonzero");
size_t bucketIndex = 0;
+
for (double bucketBoundary = MIN_BUCKET_FEERATE; bucketBoundary <= MAX_BUCKET_FEERATE; bucketBoundary *= FEE_SPACING, bucketIndex++) {
buckets.push_back(bucketBoundary);
bucketMap[bucketBoundary] = bucketIndex;
@@ -500,6 +505,13 @@ CBlockPolicyEstimator::CBlockPolicyEstimator()
feeStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
shortStats = std::unique_ptr<TxConfirmStats>(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
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 = GetDataDir() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_file(fsbridge::fopen(est_filepath, "rb"), SER_DISK, CLIENT_VERSION);
+ if (est_file.IsNull() || !Read(est_file)) {
+ LogPrintf("Failed to read fee estimates from %s. Continue anyway.\n", est_filepath.string());
+ }
}
CBlockPolicyEstimator::~CBlockPolicyEstimator()
@@ -856,6 +868,15 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation
return CFeeRate(llround(median));
}
+void CBlockPolicyEstimator::Flush() {
+ FlushUnconfirmed();
+
+ fs::path est_filepath = GetDataDir() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
+ if (est_file.IsNull() || !Write(est_file)) {
+ LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", est_filepath.string());
+ }
+}
bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
{
@@ -888,8 +909,9 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
LOCK(m_cs_fee_estimator);
int nVersionRequired, nVersionThatWrote;
filein >> nVersionRequired >> nVersionThatWrote;
- if (nVersionRequired > CLIENT_VERSION)
- return error("CBlockPolicyEstimator::Read(): up-version (%d) fee estimate file", nVersionRequired);
+ if (nVersionRequired > CLIENT_VERSION) {
+ throw std::runtime_error(strprintf("up-version (%d) fee estimate file", nVersionRequired));
+ }
// Read fee estimates file into temporary variables so existing data
// structures aren't corrupted if there is an exception.
@@ -907,8 +929,9 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
std::vector<double> fileBuckets;
filein >> fileBuckets;
size_t numBuckets = fileBuckets.size();
- if (numBuckets <= 1 || numBuckets > 1000)
+ if (numBuckets <= 1 || numBuckets > 1000) {
throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
+ }
std::unique_ptr<TxConfirmStats> fileFeeStats(new TxConfirmStats(buckets, bucketMap, MED_BLOCK_PERIODS, MED_DECAY, MED_SCALE));
std::unique_ptr<TxConfirmStats> fileShortStats(new TxConfirmStats(buckets, bucketMap, SHORT_BLOCK_PERIODS, SHORT_DECAY, SHORT_SCALE));
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 8ea8816dc3..dd9f530c99 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -215,6 +215,9 @@ public:
/** Calculation of highest target that estimates are tracked for */
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const;
+ /** Drop still unconfirmed transactions and record current estimations, if the fee estimation file is present. */
+ void Flush();
+
private:
mutable RecursiveMutex m_cs_fee_estimator;
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 69f2b456f1..8e367d31d0 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -75,7 +75,7 @@ bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
{
- if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
+ if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
return false;
}
@@ -92,14 +92,15 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR
for (const CTxIn& txin : tx.vin)
{
- // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
- // keys (remember the 520 byte limit on redeemScript size). That works
- // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
- // bytes of scriptSig, which we round off to 1650 bytes for some minor
- // future-proofing. That's also enough to spend a 20-of-20
- // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
- // considered standard.
- if (txin.scriptSig.size() > 1650) {
+ // Biggest 'standard' txin involving only keys is a 15-of-15 P2SH
+ // multisig with compressed keys (remember the 520 byte limit on
+ // redeemScript size). That works out to a (15*(33+1))+3=513 byte
+ // redeemScript, 513+1+15*(73+1)+3=1627 bytes of scriptSig, which
+ // we round off to 1650(MAX_STANDARD_SCRIPTSIG_SIZE) bytes for
+ // some minor future-proofing. That's also enough to spend a
+ // 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey
+ // is not considered standard.
+ if (txin.scriptSig.size() > MAX_STANDARD_SCRIPTSIG_SIZE) {
reason = "scriptsig-size";
return false;
}
@@ -155,7 +156,7 @@ bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeR
*
* Note that only the non-witness portion of the transaction is checked here.
*/
-bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
+bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, bool taproot_active)
{
if (tx.IsCoinBase())
return true; // Coinbases don't use vin normally
@@ -183,6 +184,9 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
return false;
}
+ } else if (whichType == TxoutType::WITNESS_V1_TAPROOT) {
+ // Don't allow Taproot spends unless Taproot is active.
+ if (!taproot_active) return false;
}
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 51d67b9390..fc163e958b 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -38,12 +38,14 @@ static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
/** The maximum number of witness stack items in a standard P2WSH script */
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100;
-/** The maximum size of each witness stack item in a standard P2WSH script */
+/** The maximum size in bytes of each witness stack item in a standard P2WSH script */
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80;
-/** The maximum size of each witness stack item in a standard BIP 342 script (Taproot, leaf version 0xc0) */
+/** The maximum size in bytes of each witness stack item in a standard BIP 342 script (Taproot, leaf version 0xc0) */
static const unsigned int MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE = 80;
-/** The maximum size of a standard witnessScript */
+/** The maximum size in bytes of a standard witnessScript */
static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
+/** The maximum size of a standard ScriptSig */
+static const 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
* standard and should be done with care and ideally rarely. It makes sense to
@@ -88,22 +90,32 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType);
- /**
- * Check for standard transaction types
- * @return True if all outputs (scriptPubKeys) use only standard transaction forms
- */
+
+
+// Changing the default transaction version requires a two step process: first
+// adapting relay policy by bumping TX_MAX_STANDARD_VERSION, and then later
+// allowing the new transaction version in the wallet/RPC.
+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);
- /**
- * Check for standard transaction types
- * @param[in] mapInputs Map of previous transactions that have outputs we're spending
- * @return True if all inputs (scriptSigs) use only standard transaction forms
- */
-bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
- /**
- * Check if the transaction is over standard P2WSH resources limit:
- * 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements
- * These limits are adequate for multi-signature up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL,
- */
+/**
+* Check for standard transaction types
+* @param[in] mapInputs Map of previous transactions that have outputs we're spending
+* @param[in] taproot_active Whether or taproot consensus rules are active (used to decide whether spends of them are permitted)
+* @return True if all inputs (scriptSigs) use only standard transaction forms
+*/
+bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, bool taproot_active);
+/**
+* Check if the transaction is over standard P2WSH resources limit:
+* 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements
+* These limits are adequate for multisignatures up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL.
+*
+* Also enforce a maximum stack item size limit and no annexes for tapscript spends.
+*/
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
/** Compute the virtual transaction size (weight reinterpreted as bytes). */
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index e6183cf2f4..245206b906 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -77,8 +77,6 @@ uint256 CTransaction::ComputeWitnessHash() const
return SerializeHash(*this, SER_GETHASH, 0);
}
-/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
-CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash{}, m_witness_hash{} {}
CTransaction::CTransaction(const CMutableTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
CTransaction::CTransaction(CMutableTransaction&& tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 00544f64fe..ec09668e7a 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -262,12 +262,6 @@ public:
// Default transaction version.
static const int32_t CURRENT_VERSION=2;
- // Changing the default transaction version requires a two step process: first
- // adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
- // bumping the default CURRENT_VERSION at which point both CURRENT_VERSION and
- // MAX_STANDARD_VERSION will be equal.
- static const int32_t MAX_STANDARD_VERSION=2;
-
// The local variables are made const to prevent unintended modification
// without updating the cached hash value. However, CTransaction is not
// actually immutable; deserialization and assignment are implemented,
@@ -287,12 +281,9 @@ private:
uint256 ComputeWitnessHash() const;
public:
- /** Construct a CTransaction that qualifies as IsNull() */
- CTransaction();
-
/** Convert a CMutableTransaction into a CTransaction. */
- explicit CTransaction(const CMutableTransaction &tx);
- CTransaction(CMutableTransaction &&tx);
+ explicit CTransaction(const CMutableTransaction& tx);
+ CTransaction(CMutableTransaction&& tx);
template <typename Stream>
inline void Serialize(Stream& s) const {
@@ -393,7 +384,6 @@ struct CMutableTransaction
};
typedef std::shared_ptr<const CTransaction> CTransactionRef;
-static inline CTransactionRef MakeTransactionRef() { return std::make_shared<const CTransaction>(); }
template <typename Tx> static inline CTransactionRef MakeTransactionRef(Tx&& txIn) { return std::make_shared<const CTransaction>(std::forward<Tx>(txIn)); }
/** A generic txid reference (txid or wtxid). */
diff --git a/src/protocol.cpp b/src/protocol.cpp
index dc8f795a0c..d7b73dfa40 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -203,7 +203,6 @@ static std::string serviceFlagToStr(size_t bit)
switch ((ServiceFlags)service_flag) {
case NODE_NONE: abort(); // impossible
case NODE_NETWORK: return "NETWORK";
- case NODE_GETUTXO: return "GETUTXO";
case NODE_BLOOM: return "BLOOM";
case NODE_WITNESS: return "WITNESS";
case NODE_COMPACT_FILTERS: return "COMPACT_FILTERS";
diff --git a/src/protocol.h b/src/protocol.h
index 309fac621c..8af34f58bd 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -273,10 +273,6 @@ enum ServiceFlags : uint64_t {
// NODE_NETWORK means that the node is capable of serving the complete block chain. It is currently
// set by all Bitcoin Core non pruned nodes, and is unset by SPV clients or other light clients.
NODE_NETWORK = (1 << 0),
- // NODE_GETUTXO means the node is capable of responding to the getutxo protocol request.
- // Bitcoin Core does not support this but a patch set called Bitcoin XT does.
- // See BIP 64 for details on how this is implemented.
- NODE_GETUTXO = (1 << 1),
// NODE_BLOOM means the node is capable and willing to handle bloom-filtered connections.
// Bitcoin Core nodes used to support this by default, without advertising this bit,
// but no longer do as of protocol version 70011 (= NO_BLOOM_VERSION)
diff --git a/src/psbt.h b/src/psbt.h
index 0951b76f83..b566726ee3 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -398,7 +398,7 @@ struct PartiallySignedTransaction
/** Merge psbt into this. The two psbts must have the same underlying CTransaction (i.e. the
* same actual Bitcoin transaction.) Returns true if the merge succeeded, false otherwise. */
- NODISCARD bool Merge(const PartiallySignedTransaction& psbt);
+ [[nodiscard]] bool Merge(const PartiallySignedTransaction& psbt);
bool AddInput(const CTxIn& txin, PSBTInput& psbtin);
bool AddOutput(const CTxOut& txout, const PSBTOutput& psbtout);
PartiallySignedTransaction() {}
@@ -605,11 +605,11 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti
* @param[in] psbtxs the PSBTs to combine
* @return error (OK if we successfully combined the transactions, other error if they were not compatible)
*/
-NODISCARD TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs);
+[[nodiscard]] TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs);
//! Decode a base64ed PSBT into a PartiallySignedTransaction
-NODISCARD bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error);
+[[nodiscard]] bool DecodeBase64PSBT(PartiallySignedTransaction& decoded_psbt, const std::string& base64_psbt, std::string& error);
//! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction
-NODISCARD bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error);
+[[nodiscard]] bool DecodeRawPSBT(PartiallySignedTransaction& decoded_psbt, const std::string& raw_psbt, std::string& error);
#endif // BITCOIN_PSBT_H
diff --git a/src/pubkey.h b/src/pubkey.h
index 0f784b86e4..d60520ac44 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -170,6 +170,15 @@ public:
/*
* Check syntactic correctness.
*
+ * When setting a pubkey (Set()) or deserializing fails (its header bytes
+ * don't match the length of the data), the size is set to 0. Thus,
+ * by checking size, one can observe whether Set() or deserialization has
+ * failed.
+ *
+ * This does not check for more than that. In particular, it does not verify
+ * that the coordinates correspond to a point on the curve (see IsFullyValid()
+ * for that instead).
+ *
* Note that this is consensus critical as CheckECDSASignature() calls it!
*/
bool IsValid() const
@@ -214,7 +223,7 @@ private:
public:
/** Construct an x-only pubkey from exactly 32 bytes. */
- XOnlyPubKey(Span<const unsigned char> bytes);
+ explicit XOnlyPubKey(Span<const unsigned char> bytes);
/** Verify a Schnorr signature against this public key.
*
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index 3d1963b6e6..3be8b664dd 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -58,14 +58,6 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent, SecureStri
ui->passEdit3->hide();
setWindowTitle(tr("Unlock wallet"));
break;
- case Decrypt: // Ask passphrase
- ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet."));
- ui->passLabel2->hide();
- ui->passEdit2->hide();
- ui->passLabel3->hide();
- ui->passEdit3->hide();
- setWindowTitle(tr("Decrypt wallet"));
- break;
case ChangePass: // Ask old passphrase + new passphrase x2
setWindowTitle(tr("Change passphrase"));
ui->warningLabel->setText(tr("Enter the old passphrase and new passphrase for the wallet."));
@@ -133,8 +125,7 @@ void AskPassphraseDialog::accept()
"</b></qt>");
} else {
assert(model != nullptr);
- if(model->setWalletEncrypted(true, newpass1))
- {
+ if (model->setWalletEncrypted(newpass1)) {
QMessageBox::warning(this, tr("Wallet encrypted"),
"<qt>" +
tr("Your wallet is now encrypted. ") + encryption_reminder +
@@ -144,9 +135,7 @@ void AskPassphraseDialog::accept()
"For security reasons, previous backups of the unencrypted wallet file "
"will become useless as soon as you start using the new, encrypted wallet.") +
"</b></qt>");
- }
- else
- {
+ } else {
QMessageBox::critical(this, tr("Wallet encryption failed"),
tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
}
@@ -176,17 +165,6 @@ void AskPassphraseDialog::accept()
QMessageBox::critical(this, tr("Wallet unlock failed"), e.what());
}
break;
- case Decrypt:
- if(!model->setWalletEncrypted(false, oldpass))
- {
- QMessageBox::critical(this, tr("Wallet decryption failed"),
- tr("The passphrase entered for the wallet decryption was incorrect."));
- }
- else
- {
- QDialog::accept(); // Success
- }
- break;
case ChangePass:
if(newpass1 == newpass2)
{
@@ -221,7 +199,6 @@ void AskPassphraseDialog::textChanged()
acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
break;
case Unlock: // Old passphrase x1
- case Decrypt:
acceptable = !ui->passEdit1->text().isEmpty();
break;
case ChangePass: // Old passphrase x1, new passphrase x2
diff --git a/src/qt/askpassphrasedialog.h b/src/qt/askpassphrasedialog.h
index 9557e72936..f3ba882277 100644
--- a/src/qt/askpassphrasedialog.h
+++ b/src/qt/askpassphrasedialog.h
@@ -26,7 +26,6 @@ public:
Encrypt, /**< Ask passphrase twice and encrypt */
Unlock, /**< Ask passphrase and unlock */
ChangePass, /**< Ask old passphrase + new passphrase twice */
- Decrypt /**< Ask passphrase and decrypt wallet */
};
explicit AskPassphraseDialog(Mode mode, QWidget *parent, SecureString* passphrase_out = nullptr);
diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp
index 2739b21a9d..2676de96d7 100644
--- a/src/qt/bantablemodel.cpp
+++ b/src/qt/bantablemodel.cpp
@@ -11,6 +11,7 @@
#include <QDateTime>
#include <QList>
+#include <QLocale>
#include <QModelIndex>
#include <QVariant>
@@ -122,7 +123,7 @@ QVariant BanTableModel::data(const QModelIndex &index, int role) const
case Bantime:
QDateTime date = QDateTime::fromMSecsSinceEpoch(0);
date = date.addSecs(rec->banEntry.nBanUntil);
- return date.toString(Qt::SystemLocaleLongDate);
+ return QLocale::system().toString(date, QLocale::LongFormat);
}
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 3055cd7da6..4e1b239bc7 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -263,7 +263,7 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
{
assert(!m_splash);
- m_splash = new SplashScreen(nullptr, networkStyle);
+ m_splash = new SplashScreen(networkStyle);
// We don't hold a direct pointer to the splash screen after creation, but the splash
// screen will take care of deleting itself when finish() happens.
m_splash->show();
@@ -505,6 +505,9 @@ int GuiMain(int argc, char* argv[])
return EXIT_SUCCESS;
}
+ // Install global event filter that makes sure that long tooltips can be word-wrapped
+ app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
+
/// 5. Now that settings and translations are available, ask user for data directory
// User language is set up: pick a data directory
bool did_show_intro = false;
@@ -576,8 +579,6 @@ int GuiMain(int argc, char* argv[])
#endif // ENABLE_WALLET
/// 9. Main GUI initialization
- // Install global event filter that makes sure that long tooltips can be word-wrapped
- app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
// Install global event filter that makes sure that out-of-focus labels do not contain text cursor.
app.installEventFilter(new GUIUtil::LabelOutOfFocusEventFilter(&app));
#if defined(Q_OS_WIN)
diff --git a/src/qt/bitcoin_locale.qrc b/src/qt/bitcoin_locale.qrc
index d438d6b3d5..a2f81c58e7 100644
--- a/src/qt/bitcoin_locale.qrc
+++ b/src/qt/bitcoin_locale.qrc
@@ -73,6 +73,7 @@
<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="tr">locale/bitcoin_tr.qm</file>
<file alias="uk">locale/bitcoin_uk.qm</file>
<file alias="ur">locale/bitcoin_ur.qm</file>
<file alias="uz@Cyrl">locale/bitcoin_uz@Cyrl.qm</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 0c2dcc3584..f2a49e5a76 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -615,10 +615,10 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel, interfaces::BlockAndH
OptionsModel* optionsModel = _clientModel->getOptionsModel();
if (optionsModel && trayIcon) {
// be aware of the tray icon disable state change reported by the OptionsModel object.
- connect(optionsModel, &OptionsModel::hideTrayIconChanged, this, &BitcoinGUI::setTrayIconVisible);
+ connect(optionsModel, &OptionsModel::showTrayIconChanged, trayIcon, &QSystemTrayIcon::setVisible);
// initialize the disable state of the tray icon with the current value in the model.
- setTrayIconVisible(optionsModel->getHideTrayIcon());
+ trayIcon->setVisible(optionsModel->getShowTrayIcon());
}
} else {
// Disable possibility to show main window via action
@@ -669,14 +669,15 @@ void BitcoinGUI::addWallet(WalletModel* walletModel)
{
if (!walletFrame) return;
if (!walletFrame->addWallet(walletModel)) return;
- const QString display_name = walletModel->getDisplayName();
- setWalletActionsEnabled(true);
rpcConsole->addWallet(walletModel);
- m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
- if (m_wallet_selector->count() == 2) {
+ if (m_wallet_selector->count() == 0) {
+ setWalletActionsEnabled(true);
+ } else if (m_wallet_selector->count() == 1) {
m_wallet_selector_label_action->setVisible(true);
m_wallet_selector_action->setVisible(true);
}
+ const QString display_name = walletModel->getDisplayName();
+ m_wallet_selector->addItem(display_name, QVariant::fromValue(walletModel));
}
void BitcoinGUI::removeWallet(WalletModel* walletModel)
@@ -1310,7 +1311,7 @@ void BitcoinGUI::updateProxyIcon()
bool proxy_enabled = clientModel->getProxyInfo(ip_port);
if (proxy_enabled) {
- if (labelProxyIcon->pixmap() == nullptr) {
+ if (!GUIUtil::HasPixmap(labelProxyIcon)) {
QString ip_port_q = QString::fromStdString(ip_port);
labelProxyIcon->setPixmap(platformStyle->SingleColorIcon(":/icons/proxy").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
labelProxyIcon->setToolTip(tr("Proxy is <b>enabled</b>: %1").arg(ip_port_q));
@@ -1386,14 +1387,6 @@ void BitcoinGUI::showProgress(const QString &title, int nProgress)
}
}
-void BitcoinGUI::setTrayIconVisible(bool fHideTrayIcon)
-{
- if (trayIcon)
- {
- trayIcon->setVisible(!fHideTrayIcon);
- }
-}
-
void BitcoinGUI::showModalOverlay()
{
if (modalOverlay && (progressBar->isVisible() || modalOverlay->isLayerVisible()))
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 912297a74e..147f19e68d 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -49,6 +49,7 @@ struct BlockAndHeaderTipInfo;
QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
+class QDateTime;
class QMenu;
class QProgressBar;
class QProgressDialog;
@@ -317,9 +318,6 @@ public Q_SLOTS:
/** Show progress dialog e.g. for verifychain */
void showProgress(const QString &title, int nProgress);
- /** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */
- void setTrayIconVisible(bool);
-
void showModalOverlay();
};
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 8b89242f6c..27e512d075 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -39,6 +39,9 @@ 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", ""
+"More than one onion bind address is provided. Using %s for the automatically "
+"created Tor onion service."),
+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", ""
@@ -50,6 +53,15 @@ 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", ""
+"SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet "
+"schema version: %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"SQLiteDatabase: Failed to prepare the statement to fetch the application id: "
+"%s"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is "
+"supported"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"The block database contains a block which appears to be from the future. "
"This may be due to your computer's date and time being set incorrectly. Only "
"rebuild the block database if you are sure that your computer's date and "
@@ -117,7 +129,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Private keys can only be di
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Wallet corrupted"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading %s: Wallet requires newer version of %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error loading block database"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Error loading wallet %s. Duplicate -wallet filename specified."),
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 upgrading chainstate database"),
@@ -125,7 +136,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low for %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Keypool ran out, please call keypoolrefill first"),
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"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Failed to verify database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Fee rate (%s) is lower than the minimum fee rate setting (%s)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Ignoring duplicate -wallet %s."),
QT_TRANSLATE_NOOP("bitcoin-core", "Importing..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"),
QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. %s is shutting down."),
@@ -153,6 +166,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Reducing -maxconnections from %d to %d, becau
QT_TRANSLATE_NOOP("bitcoin-core", "Replaying blocks..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Rewinding blocks..."),
+QT_TRANSLATE_NOOP("bitcoin-core", "SQLiteDatabase: Failed to execute statement to verify database: %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "SQLiteDatabase: Failed to fetch the application id: %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "SQLiteDatabase: Failed to prepare statement to verify database: %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "SQLiteDatabase: Failed to read database verification error: %s"),
+QT_TRANSLATE_NOOP("bitcoin-core", "SQLiteDatabase: Unexpected application id. Expected %u, got %u"),
QT_TRANSLATE_NOOP("bitcoin-core", "Section [%s] is not recognized."),
QT_TRANSLATE_NOOP("bitcoin-core", "Signing transaction failed"),
QT_TRANSLATE_NOOP("bitcoin-core", "Specified -walletdir \"%s\" does not exist"),
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index fd55c547fc..5402ed371d 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -8,6 +8,8 @@
#include <cassert>
+static constexpr auto MAX_DIGITS_BTC = 16;
+
BitcoinUnits::BitcoinUnits(QObject *parent):
QAbstractListModel(parent),
unitlist(availableUnits())
@@ -108,7 +110,9 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator
qint64 n_abs = (n > 0 ? n : -n);
qint64 quotient = n_abs / coin;
QString quotient_str = QString::number(quotient);
- if (justify) quotient_str = quotient_str.rightJustified(16 - num_decimals, ' ');
+ if (justify) {
+ quotient_str = quotient_str.rightJustified(MAX_DIGITS_BTC - num_decimals, ' ');
+ }
// Use SI-style thin space separators as these are locale independent and can't be
// confused with the decimal marker.
diff --git a/src/qt/createwalletdialog.cpp b/src/qt/createwalletdialog.cpp
index 5056e487fc..3945159c26 100644
--- a/src/qt/createwalletdialog.cpp
+++ b/src/qt/createwalletdialog.cpp
@@ -34,6 +34,32 @@ CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
ui->disable_privkeys_checkbox->setChecked(false);
}
});
+
+ connect(ui->disable_privkeys_checkbox, &QCheckBox::toggled, [this](bool checked) {
+ // Disable the encrypt_wallet_checkbox when isDisablePrivateKeysChecked is
+ // set to true, enable it when isDisablePrivateKeysChecked is false.
+ ui->encrypt_wallet_checkbox->setEnabled(!checked);
+
+ // Wallets without private keys start out blank
+ if (checked) {
+ ui->blank_wallet_checkbox->setChecked(true);
+ }
+
+ // When the encrypt_wallet_checkbox is disabled, uncheck it.
+ if (!ui->encrypt_wallet_checkbox->isEnabled()) {
+ ui->encrypt_wallet_checkbox->setChecked(false);
+ }
+ });
+
+#ifndef USE_SQLITE
+ ui->descriptor_checkbox->setToolTip(tr("Compiled without sqlite support (required for descriptor wallets)"));
+ ui->descriptor_checkbox->setEnabled(false);
+ ui->descriptor_checkbox->setChecked(false);
+#endif
+#ifndef USE_BDB
+ ui->descriptor_checkbox->setEnabled(false);
+ ui->descriptor_checkbox->setChecked(true);
+#endif
}
CreateWalletDialog::~CreateWalletDialog()
diff --git a/src/qt/forms/createwalletdialog.ui b/src/qt/forms/createwalletdialog.ui
index b592140dd7..ea713e1abd 100644
--- a/src/qt/forms/createwalletdialog.ui
+++ b/src/qt/forms/createwalletdialog.ui
@@ -38,6 +38,9 @@
<height>24</height>
</rect>
</property>
+ <property name="placeholderText">
+ <string>Wallet</string>
+ </property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
@@ -68,17 +71,33 @@
<string>Encrypt Wallet</string>
</property>
<property name="checked">
- <bool>true</bool>
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" name="advanced_options_label">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>90</y>
+ <width>130</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">font-weight:bold;</string>
+ </property>
+ <property name="text">
+ <string>Advanced options</string>
</property>
</widget>
<widget class="QCheckBox" name="disable_privkeys_checkbox">
<property name="enabled">
- <bool>false</bool>
+ <bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>20</x>
- <y>80</y>
+ <y>115</y>
<width>171</width>
<height>22</height>
</rect>
@@ -94,8 +113,8 @@
<property name="geometry">
<rect>
<x>20</x>
- <y>110</y>
- <width>171</width>
+ <y>135</y>
+ <width>220</width>
<height>22</height>
</rect>
</property>
@@ -110,7 +129,7 @@
<property name="geometry">
<rect>
<x>20</x>
- <y>140</y>
+ <y>155</y>
<width>171</width>
<height>22</height>
</rect>
@@ -128,6 +147,7 @@
<tabstop>encrypt_wallet_checkbox</tabstop>
<tabstop>disable_privkeys_checkbox</tabstop>
<tabstop>blank_wallet_checkbox</tabstop>
+ <tabstop>descriptor_checkbox</tabstop>
</tabstops>
<resources/>
<connections>
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index d210faec03..139c8e161e 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -109,39 +109,13 @@
</widget>
</item>
<item row="3" column="0">
- <widget class="QLabel" name="label_berkeleyDBVersion">
- <property name="text">
- <string>Using BerkeleyDB version</string>
- </property>
- <property name="indent">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item row="3" column="1" colspan="2">
- <widget class="QLabel" name="berkeleyDBVersion">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Datadir</string>
</property>
</widget>
</item>
- <item row="4" column="1" colspan="2">
+ <item row="3" column="1" colspan="2">
<widget class="QLabel" name="dataDir">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -163,14 +137,14 @@
</property>
</widget>
</item>
- <item row="5" column="0">
+ <item row="4" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Blocksdir</string>
</property>
</widget>
</item>
- <item row="5" column="1" colspan="2">
+ <item row="4" column="1" colspan="2">
<widget class="QLabel" name="blocksDir">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -192,14 +166,14 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Startup time</string>
</property>
</widget>
</item>
- <item row="6" column="1" colspan="2">
+ <item row="5" column="1" colspan="2">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -215,7 +189,7 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="labelNetwork">
<property name="font">
<font>
@@ -228,14 +202,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
- <item row="8" column="1" colspan="2">
+ <item row="7" column="1" colspan="2">
<widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -251,14 +225,14 @@
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Number of connections</string>
</property>
</widget>
</item>
- <item row="9" column="1" colspan="2">
+ <item row="8" column="1" colspan="2">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -274,7 +248,7 @@
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
@@ -287,14 +261,14 @@
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current block height</string>
</property>
</widget>
</item>
- <item row="11" column="1" colspan="2">
+ <item row="10" column="1" colspan="2">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -310,14 +284,14 @@
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="labelLastBlockTime">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="12" column="1" colspan="2">
+ <item row="11" column="1" colspan="2">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -333,7 +307,7 @@
</property>
</widget>
</item>
- <item row="13" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="labelMempoolTitle">
<property name="font">
<font>
@@ -346,14 +320,14 @@
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="labelNumberOfTransactions">
<property name="text">
<string>Current number of transactions</string>
</property>
</widget>
</item>
- <item row="14" column="1">
+ <item row="13" column="1">
<widget class="QLabel" name="mempoolNumberTxs">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -369,14 +343,14 @@
</property>
</widget>
</item>
- <item row="15" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="labelMemoryUsage">
<property name="text">
<string>Memory usage</string>
</property>
</widget>
</item>
- <item row="15" column="1">
+ <item row="14" column="1">
<widget class="QLabel" name="mempoolSize">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -392,7 +366,7 @@
</property>
</widget>
</item>
- <item row="13" column="2" rowspan="3">
+ <item row="12" column="2" rowspan="3">
<layout class="QVBoxLayout" name="verticalLayoutDebugButton">
<property name="spacing">
<number>3</number>
@@ -432,7 +406,7 @@
</item>
</layout>
</item>
- <item row="16" column="0">
+ <item row="15" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index 0016fb9739..88944a58a6 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -55,7 +55,7 @@
<item>
<widget class="QCheckBox" name="prune">
<property name="toolTip">
- <string>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</string>
+ <string>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.</string>
</property>
<property name="text">
<string>Prune &amp;block storage to</string>
@@ -568,12 +568,15 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_Window">
<item>
- <widget class="QCheckBox" name="hideTrayIcon">
+ <widget class="QCheckBox" name="showTrayIcon">
<property name="toolTip">
- <string>Hide the icon from the system tray.</string>
+ <string>Show the icon in the system tray.</string>
</property>
<property name="text">
- <string>&amp;Hide tray icon</string>
+ <string>&amp;Show tray icon</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
</property>
</widget>
</item>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index bab17562a6..53ffb27f50 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -43,6 +43,7 @@
#include <QKeyEvent>
#include <QLineEdit>
#include <QList>
+#include <QLocale>
#include <QMenu>
#include <QMouseEvent>
#include <QProgressDialog>
@@ -67,7 +68,7 @@ namespace GUIUtil {
QString dateTimeStr(const QDateTime &date)
{
- return date.date().toString(Qt::SystemLocaleShortDate) + QString(" ") + date.toString("hh:mm");
+ return QLocale::system().toString(date.date(), QLocale::ShortFormat) + QString(" ") + date.toString("hh:mm");
}
QString dateTimeStr(qint64 nTime)
@@ -920,4 +921,35 @@ void PopupMenu(QMenu* menu, const QPoint& point, QAction* at_action)
menu->popup(point, at_action);
}
+QDateTime StartOfDay(const QDate& date)
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+ return date.startOfDay();
+#else
+ return QDateTime(date);
+#endif
+}
+
+bool HasPixmap(const QLabel* label)
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ return !label->pixmap(Qt::ReturnByValue).isNull();
+#else
+ return label->pixmap() != nullptr;
+#endif
+}
+
+QImage GetImage(const QLabel* label)
+{
+ if (!HasPixmap(label)) {
+ return QImage();
+ }
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ return label->pixmap(Qt::ReturnByValue).toImage();
+#else
+ return label->pixmap()->toImage();
+#endif
+}
+
} // namespace GUIUtil
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 2bd94b5eb3..d7bd124884 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -289,7 +289,7 @@ namespace GUIUtil
/**
* Returns the distance in pixels appropriate for drawing a subsequent character after text.
*
- * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 13.0.
+ * In Qt 5.12 and before the QFontMetrics::width() is used and it is deprecated since Qt 5.13.
* In Qt 5.11 the QFontMetrics::horizontalAdvance() was introduced.
*/
int TextWidth(const QFontMetrics& fm, const QString& text);
@@ -303,6 +303,56 @@ namespace GUIUtil
* Call QMenu::popup() only on supported QT_QPA_PLATFORM.
*/
void PopupMenu(QMenu* menu, const QPoint& point, QAction* at_action = nullptr);
+
+ /**
+ * Returns the start-moment of the day in local time.
+ *
+ * QDateTime::QDateTime(const QDate& date) is deprecated since Qt 5.15.
+ * QDate::startOfDay() was introduced in Qt 5.14.
+ */
+ QDateTime StartOfDay(const QDate& date);
+
+ /**
+ * Returns true if pixmap has been set.
+ *
+ * QPixmap* QLabel::pixmap() is deprecated since Qt 5.15.
+ */
+ bool HasPixmap(const QLabel* label);
+ QImage GetImage(const QLabel* label);
+
+ /**
+ * Splits the string into substrings wherever separator occurs, and returns
+ * the list of those strings. Empty strings do not appear in the result.
+ *
+ * QString::split() signature differs in different Qt versions:
+ * - QString::SplitBehavior is deprecated since Qt 5.15
+ * - Qt::SplitBehavior was introduced in Qt 5.14
+ * If {QString|Qt}::SkipEmptyParts behavior is required, use this
+ * function instead of QString::split().
+ */
+ template <typename SeparatorType>
+ QStringList SplitSkipEmptyParts(const QString& string, const SeparatorType& separator)
+ {
+ #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+ return string.split(separator, Qt::SkipEmptyParts);
+ #else
+ return string.split(separator, QString::SkipEmptyParts);
+ #endif
+ }
+
+ /**
+ * Queue a function to run in an object's event loop. This can be
+ * replaced by a call to the QMetaObject::invokeMethod functor overload after Qt 5.10, but
+ * for now use a QObject::connect for compatibility with older Qt versions, based on
+ * https://stackoverflow.com/questions/21646467/how-to-execute-a-functor-or-a-lambda-in-a-given-thread-in-qt-gcd-style
+ */
+ template <typename Fn>
+ void ObjectInvoke(QObject* object, Fn&& function, Qt::ConnectionType connection = Qt::QueuedConnection)
+ {
+ QObject source;
+ QObject::connect(&source, &QObject::destroyed, object, std::forward<Fn>(function), connection);
+ }
+
} // namespace GUIUtil
#endif // BITCOIN_QT_GUIUTIL_H
diff --git a/src/qt/locale/bitcoin_af.ts b/src/qt/locale/bitcoin_af.ts
index aa09dc197b..908083dfb7 100644
--- a/src/qt/locale/bitcoin_af.ts
+++ b/src/qt/locale/bitcoin_af.ts
@@ -70,10 +70,6 @@
<translation>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.</source>
- <translation>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Copy Address</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1139,10 +1131,6 @@
<translation>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Hide the icon from the system tray.</translation>
</message>
@@ -1275,10 +1263,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Window</translation>
</message>
@@ -1453,7 +1437,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>Current total balance in watch-only addresses</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Total Amount</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>or</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1712,6 @@
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Current number of blocks</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1765,10 +1756,6 @@
<translation>Select a peer to view detailed information.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direction</translation>
</message>
@@ -1821,10 +1808,6 @@
<translation>Services</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban Score</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Connection Time</translation>
</message>
@@ -1973,14 +1956,6 @@
<translation>Outbound</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Yes</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Unknown</translation>
</message>
@@ -2079,12 +2054,24 @@
<source>Copy amount</source>
<translation>Copy amount</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Could not unlock wallet.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Code</translation>
+ <source>Amount:</source>
+ <translation>Amount:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Message:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Wallet:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2106,30 +2093,6 @@
<source>Payment information</source>
<translation>Payment information</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Address</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Amount</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Message</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Wallet</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2377,10 +2340,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Are you sure you want to send?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
- </message>
- <message>
<source>or</source>
<translation>or</translation>
</message>
@@ -2417,18 +2376,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Confirm transaction proposal</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copy PSBT to clipboard</translation>
- </message>
- <message>
<source>Send</source>
<translation>Send</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copied</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Watch-only balance:</translation>
</message>
@@ -3210,12 +3161,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No wallet has been loaded.</translation>
+ <source>Create a new wallet</source>
+ <translation>Create a new wallet</translation>
</message>
</context>
<context>
@@ -3288,6 +3239,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Export the data in the current tab to a file</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
@@ -3331,10 +3286,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: A fatal internal error occurred, see debug.log for details</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
@@ -3347,10 +3298,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>The %s developers</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
</message>
@@ -3399,14 +3346,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d of last 100 blocks have unexpected version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupt, salvage failed</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool must be at least %d MB</translation>
</message>
@@ -3531,10 +3470,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Loading P2P addresses...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Error: Disk space is too low!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Loading banlist...</translation>
</message>
@@ -3717,10 +3652,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: unknown new rules activated (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zapping all transactions from wallet...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
</message>
@@ -3733,10 +3664,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is set very high!</translation>
</message>
@@ -3781,10 +3708,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Insufficient funds</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_am.ts b/src/qt/locale/bitcoin_am.ts
index f78d4b970c..547ee1dde6 100644
--- a/src/qt/locale/bitcoin_am.ts
+++ b/src/qt/locale/bitcoin_am.ts
@@ -311,6 +311,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -330,14 +333,6 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>አድራሻ</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>መለያ ስም</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_ar.ts b/src/qt/locale/bitcoin_ar.ts
index 0209705b25..dbe680ad5c 100644
--- a/src/qt/locale/bitcoin_ar.ts
+++ b/src/qt/locale/bitcoin_ar.ts
@@ -70,8 +70,10 @@
<translation>هذه هي عناوين البيتكوين لإرسال المدفوعات. دائما تحقق من المبلغ وعنوان المستلم قبل الإرسال.</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.</source>
- <translation>هذه هي عناوين البيتكوين الخاصة بك لإستلام المدفوعات. استخدم زر "إنشاء عنوان استلام جديد" في علامة التبويب "إستلام" لإنشاء عناوين جديدة.</translation>
+ <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>هذه هي عناوين بتكوين الخاصة بك لتلقي المدفوعات. استخدم الزر "إنشاء عنوان استلام جديد" في علامة تبويب الاستلام لإنشاء عناوين جديدة.
+التوقيع ممكن فقط مع عناوين من النوع "قديم".</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -197,7 +199,7 @@
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation>تم تشفير محفظتك.</translation>
+ <translation>محفظتك ألان مشفرة</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>
@@ -441,6 +443,10 @@
<source>Processing blocks on disk...</source>
<translation>معالجة الكتل على القرص...</translation>
</message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Processed %n blocks of transaction history.</numerusform><numerusform>Processed %n block of transaction history.</numerusform><numerusform>Processed %n blocks of transaction history.</numerusform><numerusform>Processed %n blocks of transaction history.</numerusform><numerusform>Processed %n blocks of transaction history.</numerusform><numerusform>تمت معالجة٪ n من كتل سجل المعاملات.</numerusform></translation>
+ </message>
<message>
<source>%1 behind</source>
<translation>خلف %1</translation>
@@ -470,6 +476,30 @@
<translation>محدث</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp; تحميل PSBT من ملف ...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>تحميل معاملة بتكوين الموقعة جزئيًا</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>تحميل PSBT من الحافظة ...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>تحميل معاملة بتكوين الموقعة جزئيًا من الحافظة</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation>نافذة Node </translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>افتح وحدة التحكم في تصحيح أخطاء node والتشخيص</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>&amp;عناوين الإرسال</translation>
</message>
@@ -478,6 +508,10 @@
<translation>&amp;عناوين الإستقبال</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>افتح عملة بيتكوين: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>افتح المحفظة</translation>
</message>
@@ -494,10 +528,26 @@
<translation>اغلق المحفظة</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>إغلاق جميع المحافظ ...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>إغلاق جميع المحافظ ...</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>بين اشارة المساعدة %1 للحصول على قائمة من خيارات اوامر البت كوين المحتملة </translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp; إخفاء القيم</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>إخفاء القيم في علامة التبويب نظرة عامة</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>المحفظة الإفتراضية</translation>
</message>
@@ -538,6 +588,10 @@
<translation>خطأ: %1</translation>
</message>
<message>
+ <source>Warning: %1</source>
+ <translation>تحذير: %1</translation>
+ </message>
+ <message>
<source>Date: %1
</source>
<translation>التاريخ %1
@@ -603,8 +657,12 @@
<translation>المحفظة &lt;b&gt;مشفرة&lt;/b&gt; و &lt;b&gt;مقفلة&lt;/b&gt; حاليا</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>خطأ فادح حدث . لا يمكن اتمام بيتكوين بامان سيتم الخروج</translation>
+ <source>Original message:</source>
+ <translation>الرسالة الأصلية:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>حدث خطأ فادح. لم يعد بإمكان %1 المتابعة بأمان وسيتم الإنهاء.</translation>
</message>
</context>
<context>
@@ -761,6 +819,10 @@
<context>
<name>CreateWalletActivity</name>
<message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>جاري إنشاء المحفظة&lt;b&gt;%1&lt;/b&gt;.......</translation>
+ </message>
+ <message>
<source>Create wallet failed</source>
<translation>فشل إنشاء المحفظة</translation>
</message>
@@ -788,14 +850,30 @@
<translation>تشفير محفظة</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>تعطيل المفاتيح الخاصة لهذه المحفظة. لن تحتوي المحافظ ذات المفاتيح الخاصة المعطلة على مفاتيح خاصة ولا يمكن أن تحتوي على مفتاح HD أو مفاتيح خاصة مستوردة. هذا مثالي لمحافظ مشاهدة فقط فقط.</translation>
+ </message>
+ <message>
<source>Disable Private Keys</source>
<translation>إيقاف المفاتيح الخاصة</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>اصنع محفظة فارغة. لا تحتوي المحافظ الفارغة في البداية على مفاتيح خاصة أو نصوص. يمكن استيراد المفاتيح والعناوين الخاصة، أو يمكن تعيين مصدر HD في وقت لاحق.</translation>
+ </message>
+ <message>
<source>Make Blank Wallet</source>
<translation>أنشئ محفظة فارغة</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>استخدم الواصفات لإدارة scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>المحفظة الوصفية</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>إنشاء</translation>
</message>
@@ -912,6 +990,10 @@
<translation>عند النقر على "موافق" ، سيبدأ %1 في تنزيل ومعالجة سلسلة الكتل %4 الكاملة (%2 جيجابايت) بدءًا من المعاملات الأقدم في %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>تتطلب العودة إلى هذا الإعداد إعادة تنزيل سلسلة الكتل بالكامل. من الأسرع تنزيل السلسلة الكاملة أولاً وتقليمها لاحقًا. تعطيل بعض الميزات المتقدمة.</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>تُعد هذه المزامنة الأولية أمرًا شاقًا للغاية، وقد تعرض جهاز الكمبيوتر الخاص بك للمشاكل الذي لم يلاحظها أحد سابقًا. في كل مرة تقوم فيها بتشغيل %1، سيتابع التحميل من حيث تم التوقف.</translation>
</message>
@@ -932,6 +1014,10 @@
<translation>بتكوين</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>تجاهل الكتل بعد التحقق ، باستثناء أحدث %1 جيجابايت (تقليم)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
<translation>سيتم تخزين %1 جيجابايت على الأقل من البيانات في هذا الدليل، وستنمو مع الوقت.</translation>
</message>
@@ -1002,10 +1088,18 @@
<source>Hide</source>
<translation>إخفاء</translation>
</message>
- </context>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>مجهول. مزامنة الرؤوس (%1, %2%)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
+ <source>Open bitcoin URI</source>
+ <translation>افتح بتكوين URI</translation>
+ </message>
+ <message>
<source>URI:</source>
<translation>العنوان:</translation>
</message>
@@ -1013,6 +1107,14 @@
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation>فشل فتح محفظة</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation>تحذير محفظة مفتوحة</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>محفظة إفتراضية</translation>
</message>
@@ -1048,12 +1150,12 @@
<translation>عدد مؤشرات التحقق من البرنامج النصي</translation>
</message>
<message>
- <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
- <translation>إظهار ما إذا كان وكيل SOCKS5 الافتراضي الموفر تم استخدامه للوصول إلى النظراء عبر نوع الشبكة هذا.</translation>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>عنوان IP للوكيل (مثل IPv4: 127.0.0.1 / IPv6: ::1)</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>استخدام وكيل SOCKS5 منفصل للوصول إلى الأقران عبر خدمات Tor المخفية:</translation>
+ <source>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</source>
+ <translation>إظهار ما إذا كان وكيل SOCKS5 الافتراضي الموفر تم استخدامه للوصول إلى النظراء عبر نوع الشبكة هذا.</translation>
</message>
<message>
<source>Hide the icon from the system tray.</source>
@@ -1088,10 +1190,22 @@
<translation>&amp;الشبكة</translation>
</message>
<message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>يعطل بعض الميزات المتقدمة ولكن سيظل التحقق من صحة جميع الكتل بالكامل. تتطلب العودة إلى هذا الإعداد إعادة تنزيل سلسلة الكتل بالكامل. قد يكون الاستخدام الفعلي للقرص أعلى إلى حد ما.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>تقليم وحظر التخزين لـ</translation>
+ </message>
+ <message>
<source>GB</source>
<translation>جب</translation>
</message>
<message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>تتطلب العودة إلى هذا الإعداد إعادة تنزيل سلسلة الكتل بالكامل.</translation>
+ </message>
+ <message>
<source>MiB</source>
<translation>ميجا بايت</translation>
</message>
@@ -1160,10 +1274,6 @@
<translation>تور</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>قم بالاتصال بشبكة بتكوين عبر وكيل SOCKS5 منفصل لخدمات تور المخفية.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>نافذه</translation>
</message>
@@ -1188,6 +1298,10 @@
<translation>واجهة المستخدم &amp;اللغة:</translation>
</message>
<message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>سيسري هذا الإعداد بعد إعادة تشغيل %1.</translation>
+ </message>
+ <message>
<source>&amp;Unit to show amounts in:</source>
<translation>الوحدة لإظهار المبالغ فيها:</translation>
</message>
@@ -1200,10 +1314,22 @@
<translation>ما اذا أردت إظهار ميزات التحكم في العملة أم لا.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>اتصل بشبكة بتكوين من خلال وكيل SOCKS5 منفصل لخدمات Tor onion.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>استخدم بروكسي SOCKS5 منفصل للوصول إلى الأقران عبر خدمات Tor onion:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>العناوين (URL) لجهات خارجية</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
+ <translation>يتم تجاوز الخيارات المعينة في مربع الحوار هذا بواسطة سطر الأوامر أو في ملف التكوين:</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>تم</translation>
</message>
@@ -1236,6 +1362,10 @@
<translation>إعداد الخيارات</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>
+ <translation>يتم استخدام ملف التكوين لتحديد خيارات المستخدم المتقدمة التي تتجاوز إعدادات واجهة المستخدم الرسومية. بالإضافة إلى ذلك ، ستتجاوز أي خيارات سطر أوامر ملف التكوين هذا.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>خطأ</translation>
</message>
@@ -1326,8 +1456,99 @@
<source>Current total balance in watch-only addresses</source>
<translation>الرصيد الإجمالي الحالي في العناوين المشاهدة فقط</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>تم تنشيط وضع الخصوصية لعلامة التبويب "نظرة عامة". للكشف عن القيم ، قم بإلغاء تحديد الإعدادات-&gt; إخفاء القيم.</translation>
+ </message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>حوار</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>تسجيل Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>بث TX</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>نسخ إلى الحافظة</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>حفظ...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>إغلاق</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>فشل تحميل المعاملة: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>فشل توقيع المعاملة: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>تعذر توقيع المزيد من المدخلات.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>تم توقيع %1 إدخالات، ولكن لا تزال هناك حاجة إلى المزيد من التوقيعات.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>تم توقيع المعاملة بنجاح. المعاملة جاهزة للبث.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>خطأ غير معروف في معالجة المعاملة.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>تم بث المعاملة بنجاح! معرّف المعاملة: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>فشل بث المعاملة: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>نسخ PSBT إلى الحافظة.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>حفظ بيانات المعاملات</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>معاملة موقعة جزئيًا (ثنائي) (* .psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>تم حفظ PSBT على القرص.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>* يرسل %1 إلى %2</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>القيمة الإجمالية</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>أو</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1530,10 +1751,6 @@
<translation>سلسلة الكتل</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>عدد الكتل الحالي</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>تجمع الذاكرة</translation>
</message>
@@ -1546,6 +1763,14 @@
<translation>استخدام الذاكرة</translation>
</message>
<message>
+ <source>Wallet: </source>
+ <translation>محفظة:</translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(لايوجد)</translation>
+ </message>
+ <message>
<source>&amp;Reset</source>
<translation>إعادة تعيين</translation>
</message>
@@ -1570,10 +1795,6 @@
<translation>حدد نظير لعرض معلومات مفصلة.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>اللائحة البيضاء</translation>
- </message>
- <message>
<source>Direction</source>
<translation>جهة</translation>
</message>
@@ -1598,6 +1819,10 @@
<translation>وكيل المستخدم</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>نافذة Node </translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>تصغير حجم الخط</translation>
</message>
@@ -1606,12 +1831,12 @@
<translation>تكبير حجم الخط</translation>
</message>
<message>
- <source>Services</source>
- <translation>خدمات</translation>
+ <source>Permissions</source>
+ <translation>اذونات</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>نقاط الحظر</translation>
+ <source>Services</source>
+ <translation>خدمات</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1734,6 +1959,10 @@
<translation>تم تعطيل نشاط الشبكة</translation>
</message>
<message>
+ <source>Executing command without any wallet</source>
+ <translation>تنفيذ الأوامر بدون محفظة </translation>
+ </message>
+ <message>
<source>(node id: %1)</source>
<translation>(معرف العقدة: %1)</translation>
</message>
@@ -1754,14 +1983,6 @@
<translation>خارجي</translation>
</message>
<message>
- <source>Yes</source>
- <translation>نعم</translation>
- </message>
- <message>
- <source>No</source>
- <translation>لا</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>غير معرف</translation>
</message>
@@ -1797,6 +2018,10 @@
<translation>مبلغ اختياري للطلب. اترك هذا فارغًا أو صفراً لعدم طلب مبلغ محدد.</translation>
</message>
<message>
+ <source>&amp;Create new receiving address</source>
+ <translation>و إنشاء عناوين استقبال جديدة</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>مسح كل حقول النموذج المطلوبة</translation>
</message>
@@ -1840,12 +2065,32 @@
<source>Copy amount</source>
<translation>نسخ الكمية</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation> يمكن فتح المحفظة.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>رمز كيو ار</translation>
+ <source>Request payment to ...</source>
+ <translation>طلب دفع ل ...</translation>
+ </message>
+ <message>
+ <source>Address:</source>
+ <translation>العناوين:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>القيمة :</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>الرسائل</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>المحفظة:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1867,30 +2112,6 @@
<source>Payment information</source>
<translation>معلومات الدفع</translation>
</message>
- <message>
- <source>URI</source>
- <translation> URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>عنوان</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>مبلغ</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>وسم</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>رسالة </translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>محفظة</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2094,6 +2315,18 @@
<translation>هل أنت متأكد من أنك تريد أن ترسل؟</translation>
</message>
<message>
+ <source>Create Unsigned</source>
+ <translation>إنشاء غير موقع</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>حفظ بيانات المعاملات</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>معاملة موقعة جزئيًا (ثنائي) (* .psbt)</translation>
+ </message>
+ <message>
<source>or</source>
<translation>أو</translation>
</message>
@@ -2110,10 +2343,18 @@
<translation>لا يشير إلى الإستبدال بواسطة الرسوم، BIP-125.</translation>
</message>
<message>
+ <source>Total Amount</source>
+ <translation>القيمة الإجمالية</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>تأكيد الإرسال Coins</translation>
</message>
<message>
+ <source>Send</source>
+ <translation>إرسال</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>عنوان المستلم غير صالح. يرجى إعادة الفحص.</translation>
</message>
@@ -2819,12 +3060,16 @@
<source>Close wallet</source>
<translation>اغلق المحفظة</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>إغلاق جميع المحافظ ...</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>لا يوجد محفظة تم تحميلها.</translation>
+ <source>Create a new wallet</source>
+ <translation>إنشاء محفظة جديدة</translation>
</message>
</context>
<context>
@@ -2885,6 +3130,10 @@
<translation>استخراج البيانات في علامة التبويب الحالية إلى ملف</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>خطأ</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>نسخ احتياط للمحفظة</translation>
</message>
@@ -2912,10 +3161,6 @@
<context>
<name>bitcoin-core</name>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>خطأ: حدث خطأ داخلي فادح، راجع debug.log للحصول على التفاصيل</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>تجريد مخزن الكتل...</translation>
</message>
@@ -2940,11 +3185,6 @@
<translation>يرجى المساهمة إذا وجدت %s مفيداً. تفضل بزيارة %s لمزيد من المعلومات حول البرنامج.</translation>
</message>
<message>
- <source>%s corrupt, salvage failed</source>
- <translation>
-%s تالف, فشل الانقاذ.</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-الحد الأقصى للذاكرة على الأقل %d ميغابايت</translation>
</message>
@@ -3105,14 +3345,6 @@
<translation>التحقق من المحفظة (المحافظ)...</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>إزالة جميع المعاملات من المحفظة...</translation>
- </message>
- <message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>تحذير: ملف المحفظة فاسد ، تم انقاذ البيانات! تم حفظ %s الأصلي ك %s في %s؛ إذا كان رصيدك أو كانت معاملاتك غير صحيحة، فيجب عليك الإستعادة من نسخة احتياطية.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s عالٍ جداً</translation>
</message>
diff --git a/src/qt/locale/bitcoin_be.ts b/src/qt/locale/bitcoin_be.ts
index bb0c17901f..f2a022220f 100644
--- a/src/qt/locale/bitcoin_be.ts
+++ b/src/qt/locale/bitcoin_be.ts
@@ -661,6 +661,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -709,34 +712,26 @@
<source>Copy amount</source>
<translation>Капіяваць колькасць</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Капіяваць адрас</translation>
- </message>
<message>
- <source>Address</source>
- <translation>Адрас</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Колькасць</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>Немагчыма разблакаваць гаманец</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Label</source>
- <translation>Метка</translation>
+ <source>Amount:</source>
+ <translation>Колькасць:</translation>
</message>
<message>
- <source>Message</source>
- <translation>Паведамленне</translation>
+ <source>Message:</source>
+ <translation>Паведамленне:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Гаманец</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Капіяваць адрас</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1157,6 +1152,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Экспартаваць гэтыя звесткі у файл</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Памылка</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_bg.ts b/src/qt/locale/bitcoin_bg.ts
index 694c1b1008..ed59d98664 100644
--- a/src/qt/locale/bitcoin_bg.ts
+++ b/src/qt/locale/bitcoin_bg.ts
@@ -132,6 +132,10 @@
<translation>Повтори парола</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Показване на парола</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Криптирай портфейл</translation>
</message>
@@ -172,6 +176,14 @@
<translation>портфейлa е шифрован</translation>
</message>
<message>
+ <source>Wallet to be encrypted</source>
+ <translation>Портфейл за криптиране</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Вашият портфейл сега е криптиран.</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>ВАЖНО: Всички стари запазвания, които сте направили на Вашият портфейл трябва да замените с запазване на новополучения, шифриран портфейл. От съображения за сигурност, предишните запазвания на нешифрирани портфейли ще станат неизползваеми веднага, щом започнете да използвате новият, шифриран портфейл.</translation>
</message>
@@ -438,6 +450,22 @@
<translation>Актуално</translation>
</message>
<message>
+ <source>Close Wallet...</source>
+ <translation>Затвори Портфейла</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation>Затвори портфейла</translation>
+ </message>
+ <message>
+ <source>Close All Wallets...</source>
+ <translation>Затвори Всички Портфейли...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Затвори всички портфейли</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Покажи %1 помощно съобщение за да получиш лист с възможни Биткойн команди</translation>
</message>
@@ -454,6 +482,14 @@
<translation>Минимизирай</translation>
</message>
<message>
+ <source>Zoom</source>
+ <translation>Увеличи</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation>Главен Прозорец</translation>
+ </message>
+ <message>
<source>%1 client</source>
<translation>%1 клиент</translation>
</message>
@@ -511,11 +547,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Портфейлът е &lt;b&gt;криптиран&lt;/b&gt; и &lt;b&gt;заключен&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Възникна фатална грешка. Биткойн не може да продължи безопасно и ще се изключи.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1061,6 +1093,17 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>или</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1231,10 +1274,6 @@
<translation>Брой връзки</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Текущ брой блокове</translation>
- </message>
- <message>
<source>Received</source>
<translation>Получени</translation>
</message>
@@ -1335,14 +1374,6 @@
<translation>Изходящи</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Не</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Неизвестен</translation>
</message>
@@ -1401,12 +1432,28 @@
<source>Copy amount</source>
<translation>Копиране на сумата</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Не може да отключите портфейла.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR код</translation>
+ <source>Amount:</source>
+ <translation>Количество:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Име:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Съобщение:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Портфейл</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1428,26 +1475,6 @@
<source>Payment information</source>
<translation>Данни за плащането</translation>
</message>
- <message>
- <source>Address</source>
- <translation>Адрес</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Количество</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Етикет</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Съобщение</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>портфейл</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2188,12 +2215,20 @@
</context>
<context>
<name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>Затвори портфейла</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Затвори всички портфейли</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Няма зареден портфейл.</translation>
+ <source>Create a new wallet</source>
+ <translation>Създай нов портфейл</translation>
</message>
</context>
<context>
@@ -2218,6 +2253,10 @@
<translation>Изнеси данните в избрания раздел към файл</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>грешка</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Запазване на портфейла</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bn.ts b/src/qt/locale/bitcoin_bn.ts
index 5a98c56acd..10afa566b6 100644
--- a/src/qt/locale/bitcoin_bn.ts
+++ b/src/qt/locale/bitcoin_bn.ts
@@ -70,10 +70,6 @@
<translation>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.</source>
- <translation>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Copy Address</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1139,10 +1131,6 @@
<translation>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Hide the icon from the system tray.</translation>
</message>
@@ -1275,10 +1263,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Window</translation>
</message>
@@ -1453,7 +1437,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>Current total balance in watch-only addresses</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Total Amount</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>or</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1712,6 @@
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Current number of blocks</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1765,10 +1756,6 @@
<translation>Select a peer to view detailed information.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direction</translation>
</message>
@@ -1821,10 +1808,6 @@
<translation>Services</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban Score</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Connection Time</translation>
</message>
@@ -1973,14 +1956,6 @@
<translation>Outbound</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Yes</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Unknown</translation>
</message>
@@ -2079,12 +2054,24 @@
<source>Copy amount</source>
<translation>Copy amount</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Could not unlock wallet.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Code</translation>
+ <source>Amount:</source>
+ <translation>Amount:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Message:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Wallet:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2106,30 +2093,6 @@
<source>Payment information</source>
<translation>Payment information</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Address</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Amount</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Message</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Wallet</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2377,10 +2340,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Are you sure you want to send?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
- </message>
- <message>
<source>or</source>
<translation>or</translation>
</message>
@@ -2417,18 +2376,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Confirm transaction proposal</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copy PSBT to clipboard</translation>
- </message>
- <message>
<source>Send</source>
<translation>Send</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copied</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Watch-only balance:</translation>
</message>
@@ -3210,12 +3161,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No wallet has been loaded.</translation>
+ <source>Create a new wallet</source>
+ <translation>Create a new wallet</translation>
</message>
</context>
<context>
@@ -3288,6 +3239,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Export the data in the current tab to a file</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
@@ -3331,10 +3286,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: A fatal internal error occurred, see debug.log for details</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
@@ -3347,10 +3298,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>The %s developers</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
</message>
@@ -3399,14 +3346,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d of last 100 blocks have unexpected version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupt, salvage failed</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool must be at least %d MB</translation>
</message>
@@ -3531,10 +3470,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Loading P2P addresses...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Error: Disk space is too low!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Loading banlist...</translation>
</message>
@@ -3717,10 +3652,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: unknown new rules activated (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zapping all transactions from wallet...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
</message>
@@ -3733,10 +3664,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is set very high!</translation>
</message>
@@ -3781,10 +3708,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Insufficient funds</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_bs.ts b/src/qt/locale/bitcoin_bs.ts
index ef97da747a..be76c6c418 100644
--- a/src/qt/locale/bitcoin_bs.ts
+++ b/src/qt/locale/bitcoin_bs.ts
@@ -151,6 +151,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_ca.ts b/src/qt/locale/bitcoin_ca.ts
index c5a0d398ff..4faab2e7fb 100644
--- a/src/qt/locale/bitcoin_ca.ts
+++ b/src/qt/locale/bitcoin_ca.ts
@@ -23,7 +23,7 @@
</message>
<message>
<source>C&amp;lose</source>
- <translation>&amp;Tanca</translation>
+ <translation>T&amp;anca</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
@@ -70,8 +70,10 @@
<translation>Aquestes són les vostres adreces de Bitcoin per enviar els pagaments. Sempre reviseu l'import i l'adreça del destinatari abans de transferir monedes.</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.</source>
- <translation>Aquestes són les teves adreces Bitcoin per rebre pagaments. Utilitza el botó "Crear nova adreça de recepció" de la pestanya de recepció per crear noves adreces.</translation>
+ <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>Aquestes son les teves adreces de Bitcoin per rebre pagaments. Utilitza el botó "Crear nova adreça de recepció" de la pestanya de recepció per crear una nova adreça.
+Només és possible firmar amb adreces del tipus "legacy".</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>Actualitzat</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Carrega el PSBT des del fitxer ...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Carrega la transacció Bitcoin signada parcialment</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Carrega PSBT des del porta-retalls ...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Carrega la transacció de Bitcoin signada parcialment des del porta-retalls</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Finestra node</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Tanca la cartera</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Tanca totes les carteres ...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Tanqueu totes les carteres</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Mostra el missatge d'ajuda del %1 per obtenir una llista amb les possibles opcions de línia d'ordres de Bitcoin</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Emmascara els valors</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Emmascara els valors en la pestanya Visió general</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>cartera predeterminada</translation>
</message>
@@ -630,8 +664,12 @@
<translation>La cartera està &lt;b&gt;encriptada&lt;/b&gt; i actualment &lt;b&gt;blocada&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>S'ha produït un error fatal. Bitcoin no pot continuar amb seguretat i finalitzarà.</translation>
+ <source>Original message:</source>
+ <translation>Missatge original:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>S'ha produït un error fatal. %1 ja no pot continuar amb seguretat i sortirà.</translation>
</message>
</context>
<context>
@@ -836,6 +874,14 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Fes cartera en blanc</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Utilitzeu descriptors per a la gestió de scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Cartera del descriptor</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Crear</translation>
</message>
@@ -1140,10 +1186,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Mostra si el proxy SOCKS5 predeterminat subministrat s'utilitza per arribar a altres nodes a través d'aquest tipus de xarxa.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Usi un proxy SOCKS&amp;5 separat per connectar amb nodes a través dels serveis ocults de Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Amaga la icona de la safata del sistema</translation>
</message>
@@ -1276,10 +1318,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conectar a la red de Bitcoin a través de un proxy SOCKS5 per als serveis ocults de Tor</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Finestra</translation>
</message>
@@ -1320,6 +1358,14 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Si voleu mostrar les funcions de control de monedes o no.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Connecteu-vos a la xarxa Bitcoin mitjançant un servidor intermediari SOCKS5 separat per als serveis de ceba Tor.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Utilitzeu el servidor intermediari SOCKS&amp;5 per arribar als peers mitjançant els serveis d'onion de Tor:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>URL de transaccions de tercers</translation>
</message>
@@ -1454,8 +1500,43 @@ Això és ideal per a carteres de mode només lectura.</translation>
<source>Current total balance in watch-only addresses</source>
<translation>Balanç total actual en adreces de només lectura</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>El mode de privadesa està activat a la pestanya d'Overview. Per desenmascarar els valors, desmarqueu Configuració-&gt; Valors de màscara.</translation>
+ </message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Diàleg</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Signa Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Emet Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Còpia al Clipboard</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Desa...</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Import total</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1718,10 +1799,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Cadena de blocs</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Nombre de blocs actuals</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Reserva de memòria</translation>
</message>
@@ -1766,10 +1843,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Seleccioneu un igual per mostrar informació detallada.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>A la llista blanca</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direcció</translation>
</message>
@@ -1822,10 +1895,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Serveis</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Puntuació de bandeig</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Temps de connexió</translation>
</message>
@@ -1974,14 +2043,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<translation>Sortint</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Sí</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Desconegut</translation>
</message>
@@ -2080,12 +2141,24 @@ Això és ideal per a carteres de mode només lectura.</translation>
<source>Copy amount</source>
<translation>Copia l'import</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No s'ha pogut desblocar la cartera.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Codi QR</translation>
+ <source>Amount:</source>
+ <translation>Import:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Missatge:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Moneder:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2107,30 +2180,6 @@ Això és ideal per a carteres de mode només lectura.</translation>
<source>Payment information</source>
<translation>Informació de pagament</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adreça</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Import</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Missatge</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Cartera</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2378,10 +2427,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Esteu segur que ho voleu enviar?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Revisa la teva proposta de transacció. Es produirà una transacció de Bitcoin amb signatura parcial (PSBT) que podeu copiar i després signar, per exemple, amb una cartera %1 de tipus fora de línia o una cartera física compatible amb PSBT.</translation>
- </message>
- <message>
<source>or</source>
<translation>o</translation>
</message>
@@ -2418,18 +2463,10 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Confirmeu la proposta de transacció</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copiar PSBT al porta-retalls.</translation>
- </message>
- <message>
<source>Send</source>
<translation>Enviar</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copiada</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Saldo només de vigilància:</translation>
</message>
@@ -3211,12 +3248,16 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Si tanqueu la cartera durant massa temps, es pot haver de tornar a sincronitzar tota la cadena si teniu el sistema de poda habilitat.</translation>
</message>
-</context>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Tanqueu totes les carteres</translation>
+ </message>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No s'ha carregat cap cartera.</translation>
+ <source>Create a new wallet</source>
+ <translation>Crear una nova cartera</translation>
</message>
</context>
<context>
@@ -3289,6 +3330,10 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Exporta les dades de la pestanya actual a un fitxer</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Còpia de seguretat de la cartera</translation>
</message>
@@ -3332,10 +3377,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Poda: la darrera sincronització de la cartera va més enllà de les dades podades. Cal que activeu -reindex (baixeu tota la cadena de blocs de nou en cas de node podat)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: s'ha produït un error intern fatal. Vegeu debug.log per a més detalls</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>S'està podant la cadena de blocs...</translation>
</message>
@@ -3348,10 +3389,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Els desenvolupadors %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>No es pot generar una clau d’adreça de canvi. No hi ha claus al keypool intern i no es pot generar cap clau.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>No es pot obtenir un bloqueig al directori de dades %s. %s probablement ja s'estigui executant.</translation>
</message>
@@ -3400,14 +3437,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Avís: sembla que no estem plenament d'acord amb els nostres iguals! Podria caler que actualitzar l'aplicació, o potser que ho facin altres nodes.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d dels últims 100 blocs tenen una versió inesperada</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s està malmès, el rescat de les dades ha fallat</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool ha de tenir almenys %d MB</translation>
</message>
@@ -3532,10 +3561,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>S'estan carregant les adreces P2P ...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Error: l'espai del disc és insuficient.</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Carregant banlist ...</translation>
</message>
@@ -3718,10 +3743,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Avís: regles noves desconegudes activades (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Se suprimeixen totes les transaccions de la cartera..</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee especificat molt alt! Comissions tan grans podrien pagar-se en una única transacció.</translation>
</message>
@@ -3734,10 +3755,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>La longitud total de la cadena de la versió de xarxa (%i) supera la longitud màxima (%i). Redueix el nombre o la mida de uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Advertència: la cartera és malmesa, les dades es recuperen! Original %s desat com a %s en %s; si el vostre saldo o transaccions són incorrectes, haureu de restaurar des d'una còpia de seguretat.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s està especificat molt alt!</translation>
</message>
@@ -3782,10 +3799,6 @@ Nota: Com que la comissió es calcula en funció dels bytes, una comissió de "1
<translation>Balanç insuficient</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>No es pot actualitzar una cartera de tipus dividida que no sigui física sense haver d'actualitzar per tal de suportar keypool pre dividida. Si us plau, utilitzeu -upgradewallet = 169900 o -upgradewallet sense cap versió especificada.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>L'estimació de la quota ha fallat. Fallbackfee està desactivat. Espereu uns quants blocs o activeu -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_cs.ts b/src/qt/locale/bitcoin_cs.ts
index 7d6ba6772b..1ba16439a7 100644
--- a/src/qt/locale/bitcoin_cs.ts
+++ b/src/qt/locale/bitcoin_cs.ts
@@ -43,7 +43,7 @@
</message>
<message>
<source>&amp;Delete</source>
- <translation>S&amp;maž</translation>
+ <translation>&amp;Smaž</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
@@ -70,8 +70,9 @@
<translation>Tohle jsou tvé bitcoinové adresy pro posílání plateb. Před odesláním mincí si vždy zkontroluj částku a cílovou adresu.</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.</source>
- <translation>Tohle jsou tvé bitcoinové adresy pro příjem plateb. Použij 'Vytvoř novou přijímací adresu' v záložce Přijmi pro vytvoření nové adresy.</translation>
+ <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>Tohle jsou tvé bitcoinové adresy pro přijmaní plateb. Použij "Vytvoř novou přijimací adresu" pro vytvoření nových adres. Přihlašování je povoleno jen s adresami typu "Legacy"</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -275,7 +276,7 @@
</message>
<message>
<source>Browse transaction history</source>
- <translation>Procházej historii transakcí</translation>
+ <translation>Procházet historii transakcí</translation>
</message>
<message>
<source>E&amp;xit</source>
@@ -629,11 +630,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Peněženka je &lt;b&gt;zašifrovaná&lt;/b&gt; a momentálně &lt;b&gt;zamčená&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Stala se fatální chyba. Bitcoin nemůže bezpečně pokračovat v činnosti, a proto skončí.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1139,10 +1136,6 @@
<translation>Ukazuje, jestli se zadaná výchozí SOCKS5 proxy používá k připojování k peerům v rámci tohoto typu sítě.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Použít samostatnou SOCKS&amp;5 proxy ke spojení s protějšky přes skryté služby v Toru:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Skryje ikonu, která se zobrazuje v panelu.</translation>
</message>
@@ -1275,10 +1268,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Připojí se do bitcoinové sítě přes SOCKS5 proxy vyhrazenou pro skryté služby v Tor síti.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>O&amp;kno</translation>
</message>
@@ -1453,7 +1442,22 @@
<source>Current total balance in watch-only addresses</source>
<translation>Aktuální stav účtu sledovaných adres</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Celková částka</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>nebo</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1721,6 @@
<translation>Blockchain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Aktuální počet bloků</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Transakční zásobník</translation>
</message>
@@ -1765,10 +1765,6 @@
<translation>Vyber protějšek a uvidíš jeho detailní informace.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Vždy vítán</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Směr</translation>
</message>
@@ -1821,10 +1817,6 @@
<translation>Služby</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Skóre pro klatbu</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Doba spojení</translation>
</message>
@@ -1973,14 +1965,6 @@
<translation>Ven</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ano</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ne</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Neznámá</translation>
</message>
@@ -2079,12 +2063,28 @@
<source>Copy amount</source>
<translation>Kopíruj částku</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Nemohu odemknout peněženku.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR kód</translation>
+ <source>Amount:</source>
+ <translation>Částka:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Označení:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Zpráva:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Peněženka:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2106,30 +2106,6 @@
<source>Payment information</source>
<translation>Informace o platbě</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Částka</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Označení</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Zpráva</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Peněženka</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2377,10 +2353,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Jsi si jistý, že tuhle transakci chceš poslat?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Zkontrolujte prosím svůj návrh transakce. Výsledkem bude částečně podepsaná bitcoinová transakce (PSBT), kterou můžete kopírovat a poté podepsat např. pomocí offline %1 peněženky nebo hardwarové peněženky kompatibilní s PSBT.</translation>
- </message>
- <message>
<source>or</source>
<translation>nebo</translation>
</message>
@@ -2417,18 +2389,10 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Potvrdit návrh transakce</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Zkopírovat PSBT do schránky</translation>
- </message>
- <message>
<source>Send</source>
<translation>Odeslat</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT zkopírován</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Pouze sledovaný zůstatek:</translation>
</message>
@@ -3210,12 +3174,12 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Zavření peněženky na příliš dlouhou dobu může vyústit v potřebu resynchronizace celého blockchainu pokud je zapnuté prořezávání.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Žádná peněženka se nenačetla.</translation>
+ <source>Create a new wallet</source>
+ <translation>Vytvoř novou peněženku</translation>
</message>
</context>
<context>
@@ -3288,6 +3252,10 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Exportuj data z tohoto panelu do souboru</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Chyba</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Záloha peněženky</translation>
</message>
@@ -3331,10 +3299,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>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>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Chyba: Přihodila se závažná vnitřní chyba, podrobnosti viz v debug.log</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Prořezávám úložiště bloků...</translation>
</message>
@@ -3347,10 +3311,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Vývojáři %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Nelze vygenerovat klíč pro změnu adresy. Nejsou žádní klíče v key-poolu a tedy nemůžeme žádné klíče vygenerovat.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Nedaří se mi získat zámek na datový adresář %s. %s pravděpodobně už jednou běží.</translation>
</message>
@@ -3399,14 +3359,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Upozornění: Nesouhlasím zcela se svými protějšky! Možná potřebuji aktualizovat nebo ostatní uzly potřebují aktualizovat.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d z posledních 100 bloků má neočekávanou verzi</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s je poškozen, jeho záchrana se nezdařila</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool musí být alespoň %d MB</translation>
</message>
@@ -3531,10 +3483,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Načítám P2P adresy…</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Chyba: Místo na disku je příliš malé!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Načítám seznam klateb...</translation>
</message>
@@ -3717,10 +3665,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Upozornění: aktivována neznámá nová pravidla (verzový bit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Vymazat všechny transakce z peněženky...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee je nastaveno velmi vysoko! Takto vysoký poplatek může být zaplacen v jednotlivé transakci.</translation>
</message>
@@ -3733,10 +3677,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Celková délka síťového identifikačního řetězce (%i) překročila svůj horní limit (%i). Omez počet nebo velikost voleb uacomment.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Upozornění: soubor s peněženkou je poškozený, data jsou však zachráněna! Původní soubor %s je uložený jako %s v %s. Pokud nejsou stav tvého účtu nebo transakce v pořádku, zřejmě bys měl obnovit zálohu.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s je nastaveno velmi vysoko!</translation>
</message>
@@ -3781,10 +3721,6 @@ Poznámka: Jelikož je poplatek počítaný za bajt, poplatek o hodnotě "100 sa
<translation>Nedostatek prostředků</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Není možné vylepšit peněženku bez HD bez aktualizace, která podporuje dělení keypoolu. Použijte prosím -upgradewallet=169900 nebo -upgradewallet bez specifikované verze.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Odhad poplatku se nepodařil. Fallbackfee je zakázaný. Počkejte několik bloků nebo povolte -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_cy.ts b/src/qt/locale/bitcoin_cy.ts
index 3f053f7be6..cd1fe6232c 100644
--- a/src/qt/locale/bitcoin_cy.ts
+++ b/src/qt/locale/bitcoin_cy.ts
@@ -525,11 +525,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Mae'r waled &lt;b&gt;wedi'i amgryptio&lt;/b&gt; ac &lt;b&gt;ar glo&lt;/b&gt; ar hyn o bryd</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Mae gwall angheuol wedi digwydd. Ni all Bitcoin barhau'n ddiogel ac mae'n cau lawr.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -739,6 +735,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -791,34 +790,30 @@
<source>Copy amount</source>
<translation>Copïo Cyfanswm</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Cyfeiriad Copi</translation>
- </message>
<message>
- <source>Address</source>
- <translation>Cyfeiriad</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>Methodd ddatgloi'r waled.</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Amount</source>
- <translation>Cyfanswm</translation>
+ <source>Amount:</source>
+ <translation>Maint</translation>
</message>
<message>
- <source>Label</source>
- <translation>Label</translation>
+ <source>Message:</source>
+ <translation>Neges:</translation>
</message>
<message>
- <source>Message</source>
- <translation>Neges</translation>
+ <source>Wallet:</source>
+ <translation>Waled:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Waled</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Cyfeiriad Copi</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1095,6 +1090,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Allforio'r data yn y tab presennol i ffeil</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Gwall</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_da.ts b/src/qt/locale/bitcoin_da.ts
index a087ebe522..2fd4955ca8 100644
--- a/src/qt/locale/bitcoin_da.ts
+++ b/src/qt/locale/bitcoin_da.ts
@@ -70,10 +70,6 @@
<translation>Disse er dine Bitcoin-adresser til afsendelse af betalinger. Tjek altid beløb og modtagelsesadresse, inden du sender bitcoins.</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.</source>
- <translation>Disse er dine Bitcoin adresser til at modtage betalinger. Benyt 'Opret ny modtager adresse' knappen i modtag fanen for at oprette nye adresser.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopiér adresse</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Tegnebog er &lt;b&gt;krypteret&lt;/b&gt; og i øjeblikket &lt;b&gt;låst&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Der opstod en fatal fejl. Bitcoin kan ikke længere fortsætte sikkert og vil afslutte.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1139,10 +1131,6 @@
<translation>Viser om den angivne standard-SOCKS5-proxy bruges til at nå knuder via denne netværkstype.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Brug separat SOCKS&amp;5-proxy for at nå knuder via Tors skjulte tjenester:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Skjul ikonet fra statusfeltet.</translation>
</message>
@@ -1275,10 +1263,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Forbind til Bitcoin-netværket gennem en separat SOCKS5-proxy for Tors skjulte tjenester.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Vindue</translation>
</message>
@@ -1453,7 +1437,22 @@
<source>Current total balance in watch-only addresses</source>
<translation>Nuværende totalsaldo på kigge-adresser</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Total Mængde</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>eller</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1716,6 @@
<translation>Blokkæde</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Nuværende antal blokke</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Hukommelsespulje</translation>
</message>
@@ -1765,10 +1760,6 @@
<translation>Vælg en anden knude for at se detaljeret information.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>På hvidliste</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Retning</translation>
</message>
@@ -1821,10 +1812,6 @@
<translation>Tjenester</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Bandlysningsscore</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Forbindelsestid</translation>
</message>
@@ -1973,14 +1960,6 @@
<translation>Udgående</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nej</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Ukendt</translation>
</message>
@@ -2079,12 +2058,28 @@
<source>Copy amount</source>
<translation>Kopiér beløb</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Kunne ikke låse tegnebog op.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-kode</translation>
+ <source>Amount:</source>
+ <translation>Beløb:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Mærkat:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Besked:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Tegnebog:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2106,30 +2101,6 @@
<source>Payment information</source>
<translation>Betalingsinformation</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Beløb</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Mærkat</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Besked</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Tegnebog</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2409,18 +2380,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Bekræft transaktionsudkast</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Kopiér PSBT til udklipsholderen</translation>
- </message>
- <message>
<source>Send</source>
<translation>Afsend</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT kopieret</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Kiggebalance:</translation>
</message>
@@ -3202,12 +3165,12 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Lukning af tegnebog i for lang tid kan resultere i at synkronisere hele kæden forfra, hvis beskæring er aktiveret.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Ingen tegnebog er indlæst.</translation>
+ <source>Create a new wallet</source>
+ <translation>Opret en ny tegnebog</translation>
</message>
</context>
<context>
@@ -3280,6 +3243,10 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Eksportér den aktuelle visning til en fil</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Fejl</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Sikkerhedskopiér tegnebog</translation>
</message>
@@ -3323,10 +3290,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Beskæring: Seneste synkronisering rækker udover beskårne data. Du er nødt til at bruge -reindex (downloade hele blokkæden igen i fald af beskåret knude)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Fejl: En alvorlig intern fejl er opstået. Se debug.log for detaljer</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Beskærer bloklager…</translation>
</message>
@@ -3339,10 +3302,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Udviklerne af %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Kan ikke generere en bytte-adresse nøgle. Ingen nøgler i den interne nøglepulje og kan ikke generere nogle nøgler.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan ikke opnå en lås på datamappe %s. %s kører sansynligvis allerede.</translation>
</message>
@@ -3391,14 +3350,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>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>%d of last 100 blocks have unexpected version</source>
- <translation>%d af de seneste 100 blokke har en uventet version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s ødelagt, redning af data mislykkedes</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool skal være mindst %d MB</translation>
</message>
@@ -3523,10 +3474,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Indlæser P2P-adresser…</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Fejl: Disk pladsen er for lav!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Indlæser bandlysningsliste…</translation>
</message>
@@ -3709,10 +3656,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Advarsel: Ukendte nye regler aktiveret (versionsbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zapper alle transaktioner fra tegnebog…</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee er sat meget højt! Gebyrer så store risikeres betalt på en enkelt transaktion.</translation>
</message>
@@ -3725,10 +3668,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Den totale længde på netværksversionsstrengen (%i) overstiger maksimallængden (%i). Reducér antaller af eller størrelsen på uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Advarsel: Tegnebogsfil ødelagt, data reddet! Oprindelig %s gemt som %s i %s; hvis din saldo eller dine transaktioner er forkert, bør du genskabe fra en sikkerhedskopi.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s er meget højt sat!</translation>
</message>
@@ -3773,10 +3712,6 @@ Note: Siden gebyret er kalkuleret på en per-byte basis, et gebyr på "100 satos
<translation>Manglende dækning</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Kan ikke opgradere en ikke HD dele tegnebog uden opgradering til at støtte før split nøglepool. Venligst brug -upgradewallet=169900 eller -upgradewallet med ingen version specificeret.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Estimering af gebyr mislykkedes. Tilbagefaldsgebyr er deaktiveret. Vent et par blokke eller aktiver -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_de.ts b/src/qt/locale/bitcoin_de.ts
index ff272af443..659a29bc29 100644
--- a/src/qt/locale/bitcoin_de.ts
+++ b/src/qt/locale/bitcoin_de.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Rechtsklick zum Bearbeiten der Adresse oder der Bezeichnung</translation>
+ <translation>Rechtsklick zum Bearbeiten der Adresse oder der Beschreibung</translation>
</message>
<message>
<source>Create a new address</source>
@@ -70,8 +70,10 @@
<translation>Dies sind Ihre Bitcoin-Adressen zum Tätigen von Überweisungen. Bitte prüfen Sie den Betrag und die Adresse des Empfängers, bevor Sie Bitcoins überweisen.</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.</source>
- <translation>Dies sind Ihre Bitcoin-Adressen zum Empfangen von Zahlungen. Benutze den 'Neue Empfangsadresse erstellen' Button im Empfangen-Tab, um eine neue Addresse zu erstellen.</translation>
+ <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>Dies sind Ihre Bitcoin-Adressen für den Empfang von Zahlungen. Verwenden Sie die 'Neue Empfangsadresse erstellen' Taste auf der Registerkarte "Empfangen", um neue Adressen zu erstellen.
+Das Signieren ist nur mit Adressen vom Typ 'Legacy' möglich.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>Auf aktuellem Stand</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Lade PSBT aus Datei...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Lade teilsignierte Bitcoin-Transaktion</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Lade PSBT aus Zwischenablage</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Lade teilsignierte Bitcoin-Transaktion aus Zwischenablage</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Node Fenster</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Wallet schließen</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Schließe alle Wallets...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Schließe alle Wallets</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Zeige den "%1"-Hilfetext, um eine Liste mit möglichen Kommandozeilenoptionen zu erhalten</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Blende Werte aus</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Blende die Werte im Übersichtsreiter aus</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>Standard Wallet</translation>
</message>
@@ -630,8 +664,12 @@
<translation>Wallet ist &lt;b&gt;verschlüsselt&lt;/b&gt; und aktuell &lt;b&gt;gesperrt&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Ein schwerer Fehler ist aufgetreten. Bitcoin kann nicht stabil weiter ausgeführt werden und wird beendet.</translation>
+ <source>Original message:</source>
+ <translation>Original-Nachricht:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Ein fataler Fehler ist aufgetreten. %1 kann nicht länger sicher fortfahren und wird beendet.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Eine leere Wallet erstellen</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Deskriptoren für scriptPubKey Verwaltung nutzen</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Deskriptor Brieftasche</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Erstellen</translation>
</message>
@@ -1101,7 +1147,7 @@
</message>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
- <translation>Öffne Wallet&lt;b&gt;%1&lt;/b&gt; ...</translation>
+ <translation>Öffne Wallet &lt;b&gt;%1&lt;/b&gt; ...</translation>
</message>
</context>
<context>
@@ -1139,10 +1185,6 @@
<translation>Zeigt an, ob der gelieferte Standard SOCKS5 Proxy verwendet wurde, um die Peers mit diesem Netzwerktyp zu erreichen.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Separaten SOCKS5-Proxy verwenden, um Gegenstellen über versteckte Tor-Dienste zu erreichen:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Verstecke das Icon von der Statusleiste.</translation>
</message>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Über einen separaten SOCKS5 Proxy für Tor Hidden Services mit dem Bitcoin-Netzwerk verbinden.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Programmfenster</translation>
</message>
@@ -1319,6 +1357,10 @@
<translation>Legt fest, ob die "Coin Control"-Funktionen angezeigt werden.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Verbinde mit dem Bitcoin-Netzwerk über einen separaten SOCKS5-Proxy für Tor-/Onion-Dienste.</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;Externe Transaktions-URLs</translation>
</message>
@@ -1453,6 +1495,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Aktueller Gesamtbetrag in nur-beobachteten Adressen</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Datenschutz-Modus aktiviert für den Übersichtsreiter. Um die Werte einzublenden, Einstellungen-&gt;Werte ausblenden deaktivieren.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Signiere Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Rundsende Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Kopiere in Zwischenablage</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Speichern...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Schließen</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Laden der Transaktion fehlgeschlagen: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Signieren der Transaktion fehlgeschlagen: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Konnte keinerlei weitere Eingaben signieren.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>%1 Eingaben signiert, doch noch sind weitere Signaturen erforderlich.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Transaktion erfolgreich signiert. Transaktion ist bereit für Rundsendung.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Unbekannter Fehler bei der Transaktionsverarbeitung</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Transaktion erfolgreich rundgesendet! Transaktions-ID: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Rundsenden der Transaktion fehlgeschlagen: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT in Zwischenablage kopiert.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Speichere Transaktionsdaten</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Teilsignierte Transaktion (Binärdatei) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT auf Platte gespeichert.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>* Sende %1 an %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Kann die Gebühr oder den Gesamtbetrag der Transaktion nicht berechnen.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Zahlt Transaktionsgebühr:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Gesamtbetrag</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>oder</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Transaktion hat %1 unsignierte Eingaben.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Der Transaktion fehlen einige Informationen über Eingaben.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Transaktion erfordert weiterhin Signatur(en).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(doch diese Wallet kann Transaktionen nicht signieren)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(doch diese Wallet hat nicht die richtigen Schlüssel)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Transaktion ist vollständig signiert und zur Rundsendung bereit.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Transaktionsstatus ist unbekannt.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1619,6 +1788,10 @@
<translation>Fehler: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Fehler beim Initialisieren der Einstellungen: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 wurde noch nicht sicher beendet...</translation>
</message>
@@ -1717,10 +1890,6 @@
<translation>Blockchain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Aktuelle Anzahl der Blöcke</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Speicher-Pool</translation>
</message>
@@ -1765,10 +1934,6 @@
<translation>Gegenstelle auswählen, um detaillierte Informationen zu erhalten.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Auf Weißliste</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Richtung</translation>
</message>
@@ -1805,6 +1970,10 @@
<translation>Node Fenster</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Aktuelle Blockhöhe</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>Öffnet die %1-Debug-Protokolldatei aus dem aktuellen Datenverzeichnis. Dies kann bei großen Protokolldateien einige Sekunden dauern.</translation>
</message>
@@ -1817,12 +1986,12 @@
<translation>Schrift vergrößern</translation>
</message>
<message>
- <source>Services</source>
- <translation>Dienste</translation>
+ <source>Permissions</source>
+ <translation>Berechtigungen</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Sperrpunktzahl</translation>
+ <source>Services</source>
+ <translation>Dienste</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2142,6 @@
<translation>ausgehend</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nein</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Unbekannt</translation>
</message>
@@ -2079,56 +2240,60 @@
<source>Copy amount</source>
<translation>Betrag kopieren</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Wallet konnte nicht entsperrt werden.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Konnte neue %1 Adresse nicht erzeugen.</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-Code</translation>
+ <source>Request payment to ...</source>
+ <translation>Zahlung anfordern an ...</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>&amp;URI kopieren</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Adresse kopieren</translation>
+ <source>Address:</source>
+ <translation>Adresse:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>Grafik &amp;speichern...</translation>
+ <source>Amount:</source>
+ <translation>Betrag:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Zahlung anfordern an %1</translation>
+ <source>Label:</source>
+ <translation>Bezeichnung:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Zahlungsinformationen</translation>
+ <source>Message:</source>
+ <translation>Nachricht:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Wallet:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Adresse</translation>
+ <source>Copy &amp;URI</source>
+ <translation>&amp;URI kopieren</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Betrag</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Adresse kopieren</translation>
</message>
<message>
- <source>Label</source>
- <translation>Bezeichnung</translation>
+ <source>&amp;Save Image...</source>
+ <translation>Grafik &amp;speichern...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Nachricht</translation>
+ <source>Request payment to %1</source>
+ <translation>Zahlung anfordern an %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Wallet</translation>
+ <source>Payment information</source>
+ <translation>Zahlungsinformationen</translation>
</message>
</context>
<context>
@@ -2377,8 +2542,20 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Wollen Sie die Überweisung ausführen?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Bitte überprüfe deinen Transaktionsentwurf. Es wird eine teilsignierte Bitcoin Transaktion (PSBT) erzeugt, die du kopieren und dann mit z.B. einem Offline %1 Wallet oder einem PSBT-kompatiblen Hardware Wallet signieren kannst.</translation>
+ <source>Create Unsigned</source>
+ <translation>Unsigniert erstellen</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Speichere Transaktionsdaten</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Teilsignierte Transaktion (Binärdatei) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT gespeichert</translation>
</message>
<message>
<source>or</source>
@@ -2417,18 +2594,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Bestätige Transaktionsentwurf</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>PSBT kopieren</translation>
- </message>
- <message>
<source>Send</source>
<translation>Senden</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT kopiert</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Nur-Anzeige Saldo:</translation>
</message>
@@ -3210,12 +3379,28 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Wenn Sie die Wallet zu lange schließen, kann es dazu kommen, dass Sie die gesamte Chain neu synchronisieren müssen, wenn Pruning aktiviert ist.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Schließe alle Wallets</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Sicher, dass Sie alle Wallets schließen möchten?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Es wurde keine Wallet geladen.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Es wurde keine Brieftasche geladen.
+Gehen Sie zu Datei &gt; Öffnen Sie die Brieftasche, um eine Brieftasche zu laden.
+- ODER-</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Neue Wallet erstellen</translation>
</message>
</context>
<context>
@@ -3288,6 +3473,30 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Daten der aktuellen Ansicht in eine Datei exportieren</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Fehler</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Konnte PSBT aus Zwischenablage nicht entschlüsseln (ungültiges Base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Lade Transaktionsdaten</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Teilsignierte Transaktion (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PSBT-Datei muss kleiner als 100 MiB sein</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>PSBT konnte nicht entschlüsselt werden</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Wallet sichern</translation>
</message>
@@ -3331,10 +3540,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>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>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Fehler: Ein schwerer interner Fehler ist aufgetreten, siehe debug.log für Details.</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Kürze Block-Speicher...</translation>
</message>
@@ -3347,11 +3552,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Die %s-Entwickler</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Kann keinen Schlüssel für die Wechselgeld-Adresse generieren. Keine Schlüssel im internen Keypool und kann keine Schlüssel generieren.
-</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Datenverzeichnis %s kann nicht gesperrt werden. Evtl. wurde %s bereits gestartet.</translation>
</message>
@@ -3372,6 +3572,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Wenn sie %s nützlich finden, sind Helfer sehr gern gesehen. Besuchen Sie %s um mehr über das Softwareprojekt zu erfahren.</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Konnte das Statement zum Abholen der Anwendungs-ID %s nicht vorbereiten.</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>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>
@@ -3400,14 +3604,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Warnung: Wir scheinen nicht vollständig mit unseren Gegenstellen übereinzustimmen! Sie oder die anderen Knoten müssen unter Umständen Ihre Client-Software aktualisieren.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d der letzten 100 Blöcke haben eine unerwartete Version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s beschädigt, Datenrettung fehlgeschlagen</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool muss mindestens %d MB betragen</translation>
</message>
@@ -3485,6 +3681,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Fehler: Wallet konnte während der Initialisierung nicht erneut gescannt werden.</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Verifizierung der Datenbank fehlgeschlagen</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importiere...</translation>
</message>
@@ -3513,6 +3713,15 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Ungültiger Betrag für -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>Datenbank konnte nicht gelesen werden
+Verifikations-Error: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase: Unerwartete Anwendungs-ID. %u statt %u erhalten.</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>Angegebener Blöcke-Ordner "%s" existiert nicht.</translation>
</message>
@@ -3533,10 +3742,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Lade P2P-Adressen...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Fehler: Zu wenig freier Speicherplatz auf dem Datenträger!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Lade Sperrliste...</translation>
</message>
@@ -3601,6 +3806,14 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Fehler: Abhören nach eingehenden Verbindungen fehlgeschlagen (listen meldete Fehler %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s korrupt. Versuche mit dem Wallet-Werkzeug bitcoin-wallet zu retten, oder eine Sicherung wiederherzustellen.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Ein Upgrade auf eine Nicht-HD-Split-Brieftasche ist nicht möglich, ohne ein Upgrade zur Unterstützung des Pre-Split-Keypools durchzuführen. Verwenden Sie bitte die Version 169900 oder keine angegebene Version.</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>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>
@@ -3609,10 +3822,34 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Der Transaktionsbetrag ist zu klein, um ihn nach Abzug der Gebühr zu senden.</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>Dieser Fehler kann auftreten, wenn diese Brieftasche nicht ordnungsgemäß heruntergefahren und zuletzt mithilfe eines Builds mit einer neueren Version von Berkeley DB geladen wurde. Verwenden Sie in diesem Fall die Software, die diese Brieftasche zuletzt geladen hat</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>Dies ist die maximale Transaktionsgebühr, die Sie (zusätzlich zur normalen Gebühr) zahlen, um die teilweise Vermeidung von Ausgaben gegenüber der regulären Münzauswahl zu priorisieren.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Transaktion erfordert eine Wechselgeldadresse, die jedoch nicht erzeugt werden kann. Bitte zunächst keypoolrefill aufrufen.</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>Sie müssen die Datenbank mit Hilfe von -reindex neu aufbauen, um zum ungekürzten Modus zurückzukehren. Dies erfordert, dass die gesamte Blockchain erneut heruntergeladen wird.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Ein fataler interner Fehler ist aufgetreten, siehe debug.log für Details</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Kann -peerblockfilters nicht ohne -blockfilterindex setzen.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Freier Plattenspeicher zu gering!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Fehler beim Lesen der Datenbank, Ausführung wird beendet.</translation>
</message>
@@ -3625,6 +3862,14 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Fehler: Zu wenig Speicherplatz auf der Festplatte %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Fehler: Schlüsselspeicher ausgeschöpft, bitte zunächst keypoolrefill ausführen</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Der Gebührensatz (%s) ist niedriger als die Mindestgebührensatz (%s) Einstellung.</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Ungültige Onion-Adresse oder ungültiger Hostname: '%s'</translation>
</message>
@@ -3645,6 +3890,10 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Angabe eines Ports benötigt für -whitebind: '%s'</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>Kein Proxy-Server angegeben. Nutze -proxy=&lt;ip&gt; oder -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Kürzungsmodus ist nicht mit -blockfilterindex kompatibel.</translation>
</message>
@@ -3719,10 +3968,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Warnung: Unbekannte neue Regeln aktiviert (Versionsbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Lösche alle Transaktionen aus Wallet...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee ist auf einen sehr hohen Wert festgelegt! Gebühren dieser Höhe könnten für eine einzelne Transaktion bezahlt werden.</translation>
</message>
@@ -3735,10 +3980,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Gesamtlänge des Netzwerkversionstrings (%i) erreicht die maximale Länge (%i). Reduzieren Sie die Nummer oder die Größe von uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Warnung: wallet.dat beschädigt, Datenrettung erfolgreich! Original %s wurde als wallet %s in %s gespeichert. Falls Ihr Kontostand oder Transaktionen nicht korrekt sind, sollten Sie von einer Datensicherung wiederherstellen.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s wurde sehr hoch eingestellt!</translation>
</message>
@@ -3783,10 +4024,6 @@ Hinweis: Eine Gebühr von "100 Satoshis pro kB" bei einer Größe der Transaktio
<translation>Unzureichender Kontostand</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Ein Wallet das kein geteiltes HD-Wallet ist, kann kein Upgrade erfahren, wenn nicht auch der Schlüsselpool vor der Teilung ein Upgrade erfahren hat. Bitte benutzen Sie upgradewallet=169900 oder -upgradewallet ohne Angabe einer Version.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Die Gebührenabschätzung schlug fehl. Fallbackfee ist deaktiviert. Warten Sie ein paar Blöcke oder aktivieren Sie -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_el.ts b/src/qt/locale/bitcoin_el.ts
index d4787e6218..e9c08feaee 100644
--- a/src/qt/locale/bitcoin_el.ts
+++ b/src/qt/locale/bitcoin_el.ts
@@ -70,10 +70,6 @@
<translation>Αυτές είναι οι 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.</source>
- <translation>Αυτές είναι οι Bitcoin διευθύνσεις για την λήψη πληρωμών. Χρησιμοποιήσε το κουμπί 'Δημιουργία νέας διεύθυνσης λήψεων' στο παράθυρο λήψεων για την δημιουργία νέας διεύθυνσης </translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Αντιγραφή Διεύθυνσης</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Το πορτοφόλι είναι &lt;b&gt;κρυπτογραφημένο&lt;/b&gt; και &lt;b&gt;κλειδωμένο&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Εμφανίστηκε ένα μοιραίο σφάλμα. Το Bitcoin δεν μπορεί πλέον να συνεχίσει με ασφάλεια και θα σταματήσει.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1131,10 +1123,6 @@
<translation>Εμφανίζει αν ο προεπιλεγμένος διακομιστής μεσολάβησης SOCKS5 χρησιμοποιείται για την προσέγγιση χρηστών μέσω αυτού του τύπου δικτύου.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Χρησιμοποιήστε χωριστό SOCKS&amp;5 proxy για να προσεγγίσετε συνομηλίκους μέσω κρυφών υπηρεσιών Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Απόκρυψη του εικονιδίου από το συρτάρι του συστήματος.</translation>
</message>
@@ -1267,10 +1255,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Συνδεθείτε στο δίκτυο Bitcoin μέσω ενός ξεχωριστού διακομιστή μεσολάβησης SOCKS5 για κρυφές υπηρεσίες Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Παράθυρο</translation>
</message>
@@ -1442,7 +1426,34 @@
<source>Current total balance in watch-only addresses</source>
<translation>Το τρέχον συνολικό υπόλοιπο σε διευθύνσεις παρακολούθησης μόνο</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Διάλογος</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Αντιγραφή στο Πρόχειρο</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Αποθήκευση...</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Αποθήκευση Δεδομένων Συναλλαγής</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Συνολικό Ποσό</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ή</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1702,10 +1713,6 @@
<translation>Αλυσίδα μπλοκ</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Τρέχον αριθμός μπλοκ</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Πισίνα μνήμης</translation>
</message>
@@ -1750,10 +1757,6 @@
<translation>Επιλέξτε ένα χρήστη για να δείτε αναλυτικές πληροφορίες.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation> Τα στοιχεία που έχουν πρόσβαση στο σύστημα</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Κατεύθυνση</translation>
</message>
@@ -1806,10 +1809,6 @@
<translation>Υπηρεσίες</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Σκορ Aποκλεισμού</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Χρόνος σύνδεσης</translation>
</message>
@@ -1959,14 +1958,6 @@
<translation>Εξερχόμενα</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ναι</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Όχι</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Άγνωστο(α)</translation>
</message>
@@ -2065,12 +2056,24 @@
<source>Copy amount</source>
<translation>Αντιγραφή ποσού</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Δεν είναι δυνατό το ξεκλείδωμα του πορτοφολιού.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Κώδικας QR</translation>
+ <source>Amount:</source>
+ <translation>Ποσό:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Μήνυμα:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Πορτοφόλι</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2092,30 +2095,6 @@
<source>Payment information</source>
<translation>Πληροφορίες πληρωμής</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Διεύθυνση</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Ποσό</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Ετικέτα</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Μήνυμα</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Πορτοφόλι</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2360,8 +2339,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Είστε βέβαιοι ότι θέλετε να στείλετε;</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Παρακαλώ ελέγξτε την πρόταση συναλλαγής. Αυτό θα παράγει μια συναλλαγή Bitcoin με μερική υπογραφή (PSBT), την οποία μπορείτε να αντιγράψετε και στη συνέχεια να υπογράψετε με π.χ. ένα πορτοφόλι %1 εκτός σύνδεσης ή ένα πορτοφόλι υλικού συμβατό με το PSBT.</translation>
+ <source>Save Transaction Data</source>
+ <translation>Αποθήκευση Δεδομένων Συναλλαγής</translation>
</message>
<message>
<source>or</source>
@@ -2401,18 +2380,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation> Επιβεβαιώστε την πρόταση συναλλαγής</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Αντιγράψτε το PSBT στο πρόχειρο</translation>
- </message>
- <message>
<source>Send</source>
<translation>Αποστολή</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT αντιγράφηκε</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Παρακολούθηση μόνο ισορροπίας:</translation>
</message>
@@ -3190,12 +3161,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Το κλείσιμο του πορτοφολιού για πολύ μεγάλο χρονικό διάστημα μπορεί να οδηγήσει στην επανασύνδεση ολόκληρης της αλυσίδας αν είναι ενεργοποιημένη η περικοπή.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Δεν έχει φορτωθεί πορτοφόλι.</translation>
+ <source>Create a new wallet</source>
+ <translation>Δημιουργία νέου Πορτοφολιού</translation>
</message>
</context>
<context>
@@ -3268,6 +3239,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Εξαγωγή δεδομένων καρτέλας σε αρχείο</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Σφάλμα</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Αντίγραφο ασφαλείας Πορτοφολιού</translation>
</message>
@@ -3311,10 +3286,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Κλάδεμα: ο τελευταίος συγχρονισμός πορτοφολιού ξεπερνά τα κλαδεμένα δεδομένα. Πρέπει να κάνετε -reindex (κατεβάστε ολόκληρο το blockchain και πάλι σε περίπτωση κλαδέματος κόμβου)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Σφάλμα: Παρουσιάστηκε θανάσιμο εσωτερικό σφάλμα, ανατρέξτε στην ενότητα debug.log για λεπτομέρειες</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Κλάδεμα blockstore...</translation>
</message>
@@ -3327,10 +3298,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Οι προγραμματιστές %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Δεν είναι δυνατή η δημιουργία ενός κλειδιού αλλαγής διεύθυνσης. Δεν υπάρχουν κλειδιά στην εσωτερική κεντρική μονάδα κλειδιών και δεν μπορούν να δημιουργήσουν κανένα κλειδί.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Δεν είναι δυνατή η λήψη κλειδώματος στον κατάλογο δεδομένων %s. Το %s πιθανώς ήδη εκτελείται.</translation>
</message>
@@ -3379,14 +3346,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Προειδοποίηση: Δεν φαίνεται να συμφωνούμε πλήρως με τους συμμαθητές μας! Ίσως χρειαστεί να κάνετε αναβάθμιση ή ίσως χρειαστεί να αναβαθμίσετε άλλους κόμβους.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>Το %d των τελευταίων 100 μπλοκ έχει μη αναμενόμενη έκδοση</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s διεφθαρμένη, αποτυχία διάσωσης</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool πρέπει να είναι τουλάχιστον %d MB</translation>
</message>
@@ -3503,10 +3462,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Φόρτωση P2P διευθύνσεων...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation> Σφάλμα: Ο χώρος στο δίσκο είναι πολύ χαμηλός!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Φόρτωση λίστα απαγόρευσης...</translation>
</message>
@@ -3689,10 +3644,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Προειδοποίηση: Άγνωστοι νέοι κανόνες ενεργοποιήθηκαν (έκδοσηbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Μεταφορά όλων των συναλλαγών από το πορτοφόλι</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation> -maxtxfee είναι καταχωρημένο πολύ υψηλά! Έξοδα τόσο υψηλά μπορούν να πληρωθούν σε μια ενιαία συναλλαγή.</translation>
</message>
@@ -3737,10 +3688,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Ανεπαρκές κεφάλαιο</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Δεν είναι δυνατή η αναβάθμιση ενός διαχωρισμένου πορτοφολιού χωρίς HD χωρίς αναβάθμιση για να υποστηρίξετε τη διαχωριστική κλειδαριά. Παρακαλούμε χρησιμοποιήστε το -upgradewallet = 169900 ή -upgradewallet χωρίς να έχετε καθορίσει καμία έκδοση.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Η αποτίμηση του τέλους απέτυχε. Το Fallbackfee είναι απενεργοποιημένο. Περιμένετε λίγα τετράγωνα ή ενεργοποιήστε το -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 71467a915b..c55cc65b63 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -331,12 +331,12 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Sign &amp;message...</translation>
</message>
<message>
- <location line="+668"/>
+ <location line="+669"/>
<source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-746"/>
+ <location line="-747"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -431,7 +431,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+350"/>
+ <location line="+351"/>
<source>Click to disable network activity.</source>
<translation type="unfinished"></translation>
</message>
@@ -461,7 +461,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-1064"/>
+ <location line="-1065"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -556,7 +556,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location line="+555"/>
+ <location line="+556"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -617,7 +617,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation>Up to date</translation>
</message>
<message>
- <location line="-694"/>
+ <location line="-695"/>
<source>&amp;Load PSBT from file...</source>
<translation type="unfinished"></translation>
</message>
@@ -737,7 +737,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+245"/>
+ <location line="+246"/>
<source>%1 client</source>
<translation type="unfinished"></translation>
</message>
@@ -1108,6 +1108,11 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<source>Create</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location line="+20"/>
+ <source>Compiled without sqlite support (required for descriptor wallets)</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>EditAddressDialog</name>
@@ -2265,7 +2270,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+102"/>
+ <location filename="../bitcoin.cpp" line="+105"/>
<source>Error: Specified data directory &quot;%1&quot; does not exist.</source>
<translation type="unfinished"></translation>
</message>
@@ -2285,7 +2290,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+65"/>
+ <location line="+63"/>
<source>%1 didn&apos;t yet exit safely...</source>
<translation type="unfinished"></translation>
</message>
@@ -2298,7 +2303,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<context>
<name>QRImageWidget</name>
<message>
- <location filename="../qrimagewidget.cpp" line="+29"/>
+ <location filename="../qrimagewidget.cpp" line="+30"/>
<source>&amp;Save Image...</source>
<translation type="unfinished"></translation>
</message>
@@ -2318,7 +2323,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+39"/>
+ <location line="+41"/>
<source>QR code support not available.</source>
<translation type="unfinished"></translation>
</message>
@@ -2996,7 +3001,7 @@ Signing is only possible with addresses of the type &apos;legacy&apos;.</source>
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+662"/>
+ <location filename="../sendcoinsdialog.cpp" line="+664"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -3378,7 +3383,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
- <location line="+118"/>
+ <location line="+124"/>
<source>Estimated to begin confirmation within %n block(s).</source>
<translation>
<numerusform>Estimated to begin confirmation within %n block.</numerusform>
@@ -3991,7 +3996,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="+221"/>
+ <location filename="../transactiontablemodel.cpp" line="+251"/>
<source>Date</source>
<translation type="unfinished">Date</translation>
</message>
@@ -4362,7 +4367,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of &quot;100 satos
<context>
<name>WalletFrame</name>
<message>
- <location filename="../walletframe.cpp" line="+37"/>
+ <location filename="../walletframe.cpp" line="+39"/>
<source>No wallet has been loaded.
Go to File &gt; Open Wallet to load a wallet.
- OR -</source>
@@ -4538,7 +4543,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+20"/>
+ <location line="+23"/>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
<translation type="unfinished"></translation>
</message>
@@ -4548,17 +4553,17 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+102"/>
+ <location line="+112"/>
<source>Pruning blockstore...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+30"/>
+ <location line="+36"/>
<source>Unable to start HTTP server. See debug log for details.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-169"/>
+ <location line="-188"/>
<source>The %s developers</source>
<translation type="unfinished"></translation>
</message>
@@ -4579,6 +4584,11 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+11"/>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<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>
@@ -4589,6 +4599,21 @@ Go to File &gt; Open Wallet to load a wallet.
</message>
<message>
<location line="+8"/>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>The block database contains a block which appears to be from the future. This may be due to your computer&apos;s date and time being set incorrectly. Only rebuild the block database if you are sure that your computer&apos;s date and time are correct</source>
<translation type="unfinished"></translation>
</message>
@@ -4703,7 +4728,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation>Error loading block database</translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
<source>Error opening block database</source>
<translation>Error opening block database</translation>
</message>
@@ -4718,7 +4743,17 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
+ <location line="+1"/>
+ <source>Failed to verify database</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+2"/>
+ <source>Ignoring duplicate -wallet %s.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Importing...</source>
<translation type="unfinished"></translation>
</message>
@@ -4753,7 +4788,37 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+23"/>
+ <location line="+18"/>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
<source>Specified blocks directory &quot;%s&quot; does not exist.</source>
<translation type="unfinished"></translation>
</message>
@@ -4773,7 +4838,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-47"/>
+ <location line="-53"/>
<source>Loading P2P addresses...</source>
<translation type="unfinished"></translation>
</message>
@@ -4808,7 +4873,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+14"/>
<source>The source code is available from %s.</source>
<translation type="unfinished"></translation>
</message>
@@ -4853,7 +4918,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-159"/>
+ <location line="-178"/>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation type="unfinished"></translation>
</message>
@@ -4873,7 +4938,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+19"/>
+ <location line="+31"/>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation type="unfinished"></translation>
</message>
@@ -4913,7 +4978,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+12"/>
+ <location line="+11"/>
<source>Error reading from database, shutting down.</source>
<translation type="unfinished"></translation>
</message>
@@ -4933,12 +4998,12 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+4"/>
<source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+6"/>
<source>Invalid -onion address or hostname: &apos;%s&apos;</source>
<translation type="unfinished"></translation>
</message>
@@ -4978,7 +5043,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+10"/>
<source>Section [%s] is not recognized.</source>
<translation type="unfinished"></translation>
</message>
@@ -5059,12 +5124,12 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-177"/>
+ <location line="-196"/>
<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="+56"/>
+ <location line="+68"/>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation type="unfinished"></translation>
</message>
@@ -5079,12 +5144,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+23"/>
- <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+42"/>
+ <location line="+72"/>
<source>Starting network threads...</source>
<translation type="unfinished"></translation>
</message>
@@ -5124,17 +5184,17 @@ Go to File &gt; Open Wallet to load a wallet.
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-53"/>
+ <location line="-59"/>
<source>Insufficient funds</source>
<translation>Insufficient funds</translation>
</message>
<message>
- <location line="-97"/>
+ <location line="-110"/>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+51"/>
+ <location line="+63"/>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation type="unfinished"></translation>
</message>
@@ -5144,7 +5204,7 @@ Go to File &gt; Open Wallet to load a wallet.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+40"/>
+ <location line="+41"/>
<source>Loading block index...</source>
<translation>Loading block index...</translation>
</message>
@@ -5154,17 +5214,17 @@ Go to File &gt; Open Wallet to load a wallet.
<translation>Loading wallet...</translation>
</message>
<message>
- <location line="-44"/>
+ <location line="-45"/>
<source>Cannot downgrade wallet</source>
<translation>Cannot downgrade wallet</translation>
</message>
<message>
- <location line="+54"/>
+ <location line="+55"/>
<source>Rescanning...</source>
<translation>Rescanning...</translation>
</message>
<message>
- <location line="-42"/>
+ <location line="-43"/>
<source>Done loading</source>
<translation>Done loading</translation>
</message>
diff --git a/src/qt/locale/bitcoin_en_GB.ts b/src/qt/locale/bitcoin_en_GB.ts
index 4d943fd532..3896953215 100644
--- a/src/qt/locale/bitcoin_en_GB.ts
+++ b/src/qt/locale/bitcoin_en_GB.ts
@@ -70,8 +70,10 @@
<translation>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.</source>
- <translation>These are your Bitcoin addresses for receiving payments. Use the 'Create new receiving address' button in the receive tab to create new addresses.</translation>
+ <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>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>
@@ -121,7 +123,7 @@
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation>Passphrase Dialog</translation>
+ <translation>Passphrase Dialogue</translation>
</message>
<message>
<source>Enter passphrase</source>
@@ -259,7 +261,7 @@
</message>
<message>
<source>Synchronizing with network...</source>
- <translation>Synchronizing with network...</translation>
+ <translation>Synchronising with network...</translation>
</message>
<message>
<source>&amp;Overview</source>
@@ -482,6 +484,22 @@
<translation>Up to date</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Load PSBT from file...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Load Partially Signed Bitcoin Transaction</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Load PSBT from clipboard...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Load Partially Signed Bitcoin Transaction from clipboard</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Node window</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Close wallet</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Close All Wallets...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Close all wallets</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Show the %1 help message to get a list with possible Bitcoin command-line options</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Mask values</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Mask the values in the Overview tab</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>default wallet</translation>
</message>
@@ -630,8 +664,12 @@
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</translation>
+ <source>Original message:</source>
+ <translation>Original message:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>A fatal error occurred. %1 can no longer continue safely and will quit.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Make Blank Wallet</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Use descriptors for scriptPubKey management</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Descriptor Wallet</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Create</translation>
</message>
@@ -1139,10 +1185,6 @@
<translation>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Hide the icon from the system tray.</translation>
</message>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Window</translation>
</message>
@@ -1319,6 +1357,14 @@
<translation>Whether to show coin control features or not.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;Third party transaction URLs</translation>
</message>
@@ -1453,6 +1499,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Current total balance in watch-only addresses</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Sign Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Broadcast Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Copy to Clipboard</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Save...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Close</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Failed to load transaction: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Failed to sign transaction: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Could not sign any more inputs.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Signed %1 inputs, but more signatures are still required.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Signed transaction successfully. Transaction is ready to broadcast.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Unknown error processing transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Transaction broadcast successfully! Transaction ID: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Transaction broadcast failed: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT copied to clipboard.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Save Transaction Data</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Partially Signed Transaction (Binary) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT saved to disk.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation> * Sends %1 to %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Unable to calculate transaction fee or total transaction amount.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Pays transaction fee: </translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Total Amount</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>or</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Transaction has %1 unsigned inputs.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Transaction is missing some information about inputs.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Transaction still needs signature(s).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(But this wallet cannot sign transactions.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(But this wallet does not have the right keys.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Transaction is fully signed and ready for broadcast.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Transaction status is unknown.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1619,6 +1792,10 @@
<translation>Error: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Error initializing settings: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 didn't yet exit safely...</translation>
</message>
@@ -1717,10 +1894,6 @@
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Current number of blocks</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1765,10 +1938,6 @@
<translation>Select a peer to view detailed information.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direction</translation>
</message>
@@ -1805,6 +1974,10 @@
<translation>Node window</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Current block height</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>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</translation>
</message>
@@ -1817,12 +1990,12 @@
<translation>Increase font size</translation>
</message>
<message>
- <source>Services</source>
- <translation>Services</translation>
+ <source>Permissions</source>
+ <translation>Permissions</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban Score</translation>
+ <source>Services</source>
+ <translation>Services</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2146,6 @@
<translation>Outbound</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Yes</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Unknown</translation>
</message>
@@ -2079,56 +2244,60 @@
<source>Copy amount</source>
<translation>Copy amount</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Could not unlock wallet.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Could not generate new %1 address</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Code</translation>
+ <source>Request payment to ...</source>
+ <translation>Request payment to ...</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>Copy &amp;URI</translation>
+ <source>Address:</source>
+ <translation>Address:</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Copy &amp;Address</translation>
+ <source>Amount:</source>
+ <translation>Amount:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Save Image...</translation>
+ <source>Label:</source>
+ <translation>Label:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Request payment to %1</translation>
- </message>
- <message>
- <source>Payment information</source>
- <translation>Payment information</translation>
+ <source>Message:</source>
+ <translation>Message:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Wallet:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Address</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copy &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Amount</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Copy &amp;Address</translation>
</message>
<message>
- <source>Label</source>
- <translation>Label</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Save Image...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Message</translation>
+ <source>Request payment to %1</source>
+ <translation>Request payment to %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Wallet</translation>
+ <source>Payment information</source>
+ <translation>Payment information</translation>
</message>
</context>
<context>
@@ -2377,8 +2546,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Are you sure you want to send?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
+ <source>Create Unsigned</source>
+ <translation>Create Unsigned</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Save Transaction Data</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Partially Signed Transaction (Binary) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT saved</translation>
</message>
<message>
<source>or</source>
@@ -2389,6 +2570,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>You can increase the fee later (signals 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>
+ <translation>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.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Please, review your transaction.</translation>
</message>
@@ -2417,18 +2602,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Confirm transaction proposal</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copy PSBT to clipboard</translation>
- </message>
- <message>
<source>Send</source>
<translation>Send</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copied</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Watch-only balance:</translation>
</message>
@@ -3210,12 +3387,28 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>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>Close all wallets</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Are you sure you wish to close all wallets?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No wallet has been loaded.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Create a new wallet</translation>
</message>
</context>
<context>
@@ -3288,6 +3481,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Export the data in the current tab to a file</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Unable to decode PSBT from clipboard (invalid base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Load Transaction Data</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Partially Signed Transaction (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PSBT file must be smaller than 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Unable to decode PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
@@ -3331,10 +3548,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: A fatal internal error occurred, see debug.log for details</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
@@ -3347,10 +3560,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>The %s developers</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
</message>
@@ -3399,14 +3608,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d of last 100 blocks have unexpected version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupt, salvage failed</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool must be at least %d MB</translation>
</message>
@@ -3531,10 +3732,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Loading P2P addresses...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Error: Disk space is too low!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Loading banlist...</translation>
</message>
@@ -3599,6 +3796,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Error: Listening for incoming connections failed (listen returned error %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</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>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</translation>
</message>
@@ -3607,10 +3812,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>The transaction amount is too small to send after the fee has been deducted</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>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</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>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</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>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>A fatal internal error occurred, see debug.log for details</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Cannot set -peerblockfilters without -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Disk space is too low!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Error reading from database, shutting down.</translation>
</message>
@@ -3623,6 +3852,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Error: Disk space is low for %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Error: Keypool ran out, please call keypoolrefill first</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Fee rate (%s) is lower than the minimum fee rate setting (%s)</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Invalid -onion address or hostname: '%s'</translation>
</message>
@@ -3643,6 +3880,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Need to specify a port with -whitebind: '%s'</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Prune mode is incompatible with -blockfilterindex.</translation>
</message>
@@ -3717,10 +3958,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: unknown new rules activated (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zapping all transactions from wallet...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
</message>
@@ -3733,10 +3970,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is set very high!</translation>
</message>
@@ -3781,10 +4014,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Insufficient funds</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_eo.ts b/src/qt/locale/bitcoin_eo.ts
index f4ce75f428..ab0167cf17 100644
--- a/src/qt/locale/bitcoin_eo.ts
+++ b/src/qt/locale/bitcoin_eo.ts
@@ -439,11 +439,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Monujo estas &lt;b&gt;ĉifrita&lt;/b&gt; kaj aktuale &lt;b&gt;ŝlosita&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Okazis neriparebla eraro. Bitmono ne plu povas sekure daŭri, do ĝi sekure ĉesos.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -893,6 +889,13 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>aŭ</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1043,10 +1046,6 @@
<translation>Blokĉeno</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Aktuala nombro de blokoj</translation>
- </message>
- <message>
<source>Received</source>
<translation>Ricevita</translation>
</message>
@@ -1153,12 +1152,24 @@
<source>Copy amount</source>
<translation>Kopii sumon</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Ne eblis malŝlosi monujon.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-kodo</translation>
+ <source>Amount:</source>
+ <translation>Sumo:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Etikedo:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mesaĝo:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1180,30 +1191,6 @@
<source>Payment information</source>
<translation>Paginformoj</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adreso</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Sumo</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etikedo</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mesaĝo</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Monujo</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1910,6 +1897,10 @@
<translation>Eksporti la datumojn el la aktuala langeto al dosiero</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Eraro</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Krei sekurkopion de monujo</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es.ts b/src/qt/locale/bitcoin_es.ts
index e4c28c4704..0b32703779 100644
--- a/src/qt/locale/bitcoin_es.ts
+++ b/src/qt/locale/bitcoin_es.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Haga clic con el botón derecho para editar una dirección o etiqueta</translation>
+ <translation>Haz click con el botón derecho para editar una dirección o etiqueta</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>Crear una nueva dirección</translation>
+ <translation>Crear una dirección nueva</translation>
</message>
<message>
<source>&amp;New</source>
@@ -31,7 +31,7 @@
</message>
<message>
<source>Enter address or label to search</source>
- <translation>Introduzca la dirección, ID de transacción o etiqueta a buscar.</translation>
+ <translation>Introduce la dirección o etiqueta que quieres buscar</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -43,11 +43,11 @@
</message>
<message>
<source>&amp;Delete</source>
- <translation>Eliminar</translation>
+ <translation>&amp;Borrar</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Escoja la dirección a la que se enviarán monedas</translation>
+ <translation>Elige la dirección a la que se enviarán las monedas</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
@@ -70,12 +70,14 @@
<translation>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.</source>
- <translation>Estas son sus direcciones Bitcoin para la recepción de pagos. Use el botón 'Crear una nueva dirección para recepción' en la pestaña Recibir para crear nuevas direcciones</translation>
+ <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>Estas son sus direcciones Bitcoin para la recepción de pagos. Use 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 correos del tipo Legacy.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>Copiar dirección</translation>
+ <translation>&amp;Copiar dirección</translation>
</message>
<message>
<source>Copy &amp;Label</source>
@@ -95,7 +97,7 @@
</message>
<message>
<source>Exporting Failed</source>
- <translation>La exportación falló</translation>
+ <translation>La exportación ha fallado</translation>
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
@@ -125,7 +127,7 @@
</message>
<message>
<source>Enter passphrase</source>
- <translation>Introducir contraseña</translation>
+ <translation>Introduce la contraseña</translation>
</message>
<message>
<source>New passphrase</source>
@@ -141,23 +143,23 @@
</message>
<message>
<source>Encrypt wallet</source>
- <translation>Cifrar monedero</translation>
+ <translation>Cifrar cartera</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
- <translation>Esta operación requiere su contraseña para desbloquear el monedero.</translation>
+ <translation>Esta operación necesita la contraseña para desbloquear la cartera</translation>
</message>
<message>
<source>Unlock wallet</source>
- <translation>Desbloquear monedero</translation>
+ <translation>Desbloquear cartera</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to decrypt the wallet.</source>
- <translation>Esta operación requiere su contraseña para descifrar el monedero.</translation>
+ <translation>Esta operación necesita la contraseña para desbloquear la cartera.</translation>
</message>
<message>
<source>Decrypt wallet</source>
- <translation>Descifrar monedero</translation>
+ <translation>Descifrar cartera</translation>
</message>
<message>
<source>Change passphrase</source>
@@ -165,7 +167,7 @@
</message>
<message>
<source>Confirm wallet encryption</source>
- <translation>Confirmar el cifrado del monedero</translation>
+ <translation>Confirma el cifrado de esta 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>
@@ -173,47 +175,47 @@
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
- <translation>¿Seguro que desea cifrar su monedero?</translation>
+ <translation>¿Seguro que quieres cifrar tu cartera?</translation>
</message>
<message>
<source>Wallet encrypted</source>
- <translation>Monedero cifrado</translation>
+ <translation>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>Introduzca la nueva contraseña del monedero. &lt;br/&gt;Por favor utilice una contraseña de &lt;b&gt;diez o más caracteres aleatorios&lt;/b&gt;, u &lt;b&gt;ocho o más palabras&lt;/b&gt;.</translation>
+ <translation>Introduce la contraseña nueva para la cartera. &lt;br/&gt;Por favor utiliza una contraseña de &lt;b&gt;diez o más caracteres aleatorios&lt;/b&gt;, u &lt;b&gt;ocho o más palabras&lt;/b&gt;.</translation>
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation>Introduzca la contraseña antigua y la nueva para el monedero.</translation>
+ <translation>Introduce la contraseña antigua y la nueva para la cartera.</translation>
</message>
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
- <translation>Recuerde que cifrar su monedero no garantiza mantener a salvo sus bitcoins en caso de tener virus en el computador.</translation>
+ <translation>Recuerda que cifrar tu cartera no garantiza la protección de tus bitcoin si tu ordenador es infectado con malware.</translation>
</message>
<message>
<source>Wallet to be encrypted</source>
- <translation>Monedero para cifrar</translation>
+ <translation>Cartera a cifrar</translation>
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation>Su monedero va a ser cifrado</translation>
+ <translation>Tu cartera va a ser cifrada</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation>Su monedero está ahora cifrado</translation>
+ <translation>Tu cartera ya está cifrada</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>IMPORTANTE: Cualquier copia de seguridad anterior que haya hecho de su archivo del monedero debe ser reemplazada por el archivo del monedero cifrado y recién generado. Por razones de seguridad, las copias de seguridad anteriores del archivo del monedero sin cifrar serán inútiles tan pronto como empiece a usar el nuevo monedero cifrado.</translation>
+ <translation>IMPORTANTE: Cualquier copia de seguridad que hayas hecho del archivo de tu cartera debe ser reemplazada por el archivo cifrado de la cartera recién generado. Por razones de seguridad, las copias de seguridad anteriores del archivo de la cartera sin cifrar serán inútiles cuando empiece a usar la nueva cartera cifrada.</translation>
</message>
<message>
<source>Wallet encryption failed</source>
- <translation>Cifrado del monedero fallido</translation>
+ <translation>El cifrado de la cartera ha fallado</translation>
</message>
<message>
<source>Wallet encryption failed due to an internal error. Your wallet was not encrypted.</source>
- <translation>El cifrado del monedero falló debido a un error interno. Su monedero no fue cifrado.</translation>
+ <translation>El cifrado de la cartera ha fallado debido a un error interno. Tu cartera no ha sido cifrada.</translation>
</message>
<message>
<source>The supplied passphrases do not match.</source>
@@ -221,19 +223,19 @@
</message>
<message>
<source>Wallet unlock failed</source>
- <translation>Desbloquear el monedero falló.</translation>
+ <translation>El desbloqueo de la cartera ha fallado</translation>
</message>
<message>
<source>The passphrase entered for the wallet decryption was incorrect.</source>
- <translation>La contraseña ingresada para el descifrado del monedero es incorrecta.</translation>
+ <translation>La contraseña introducida descifrar la cartera es incorrecta.</translation>
</message>
<message>
<source>Wallet decryption failed</source>
- <translation>El descifrado del monedero falló</translation>
+ <translation>El descifrado de la cartera ha fallado</translation>
</message>
<message>
<source>Wallet passphrase was successfully changed.</source>
- <translation>La contraseña del monedero ha sido cambiada con éxito.</translation>
+ <translation>La contraseña de la cartera ha sido cambiada.</translation>
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
@@ -248,7 +250,7 @@
</message>
<message>
<source>Banned Until</source>
- <translation>Prohibido Hasta</translation>
+ <translation>Prohibido hasta</translation>
</message>
</context>
<context>
@@ -267,7 +269,7 @@
</message>
<message>
<source>Show general overview of wallet</source>
- <translation>Mostrar vista general del monedero</translation>
+ <translation>Mostrar vista general de la cartera</translation>
</message>
<message>
<source>&amp;Transactions</source>
@@ -311,11 +313,11 @@
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>&amp;Cifrar monedero…</translation>
+ <translation>&amp;Cifrar cartera…</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;Copia de respaldo del monedero...</translation>
+ <translation>&amp;Copia de seguridad de la cartera...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
@@ -327,15 +329,15 @@
</message>
<message>
<source>Create Wallet...</source>
- <translation>Crear monedero...</translation>
+ <translation>Crear cartera...</translation>
</message>
<message>
<source>Create a new wallet</source>
- <translation>Crear monedero nuevo</translation>
+ <translation>Crear nueva cartera</translation>
</message>
<message>
<source>Wallet:</source>
- <translation>Monedero:</translation>
+ <translation>Cartera:</translation>
</message>
<message>
<source>Click to disable network activity.</source>
@@ -395,7 +397,7 @@
</message>
<message>
<source>Encrypt the private keys that belong to your wallet</source>
- <translation>Encriptar las claves privadas que pertenecen a su billetera</translation>
+ <translation>Cifrar las claves privadas que pertenecen a tu cartera</translation>
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
@@ -482,6 +484,22 @@
<translation>Actualizado</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Cargar PSBT desde el archivo...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Cargar una transacción de Bitcoin parcialmente firmada</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Cargar PSBT desde el portapapeles...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Cargar una transacción de Bitcoin parcialmente firmada desde el Portapapeles</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Ventana de nodo</translation>
</message>
@@ -503,31 +521,47 @@
</message>
<message>
<source>Open Wallet</source>
- <translation>Abrir Monedero</translation>
+ <translation>Abrir cartera</translation>
</message>
<message>
<source>Open a wallet</source>
- <translation>Abrir un monedero</translation>
+ <translation>Abrir una cartera</translation>
</message>
<message>
<source>Close Wallet...</source>
- <translation>Cerrar Monedero...</translation>
+ <translation>Cerrar cartera...</translation>
</message>
<message>
<source>Close wallet</source>
- <translation>Cerrar monedero</translation>
+ <translation>Cerrar cartera</translation>
+ </message>
+ <message>
+ <source>Close All Wallets...</source>
+ <translation>Cerrar todas las carteras...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Cerrar todas las carteras</translation>
</message>
<message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>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>&amp;Esconder valores</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Esconder los valores de la ventana de previsualización</translation>
+ </message>
+ <message>
<source>default wallet</source>
- <translation>Monedero predeterminado</translation>
+ <translation>Cartera predeterminada</translation>
</message>
<message>
<source>No wallets available</source>
- <translation>No hay monederos disponibles.</translation>
+ <translation>No hay carteras disponibles</translation>
</message>
<message>
<source>&amp;Window</source>
@@ -580,7 +614,7 @@
<message>
<source>Wallet: %1
</source>
- <translation>Monedero: %1
+ <translation>Cartera: %1
</translation>
</message>
<message>
@@ -627,11 +661,15 @@
</message>
<message>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
- <translation>El monedero está &lt;b&gt;cifrado&lt;/b&gt; y actualmente &lt;b&gt;bloqueado&lt;/b&gt;</translation>
+ <translation>La cartera está &lt;b&gt;cifrada&lt;/b&gt; y &lt;b&gt;bloqueada&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Se produjo un error fatal. Bitcoin ya no puede continuar de manera segura y se cerrará</translation>
+ <source>Original message:</source>
+ <translation>Mensaje original:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Ha ocurrido un error fatal. %1 no puede seguir seguro y se cerrará.</translation>
</message>
</context>
<context>
@@ -793,7 +831,7 @@
</message>
<message>
<source>Create wallet failed</source>
- <translation>Crear monedero falló</translation>
+ <translation>Error al crear cartera</translation>
</message>
<message>
<source>Create wallet warning</source>
@@ -835,6 +873,14 @@
<translation>Crear monedero vacío</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Use descriptores para la gestión de scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Descriptor del monedero</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Crear</translation>
</message>
@@ -992,7 +1038,7 @@
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
- <translation>El monedero también se almacenará en este directorio.</translation>
+ <translation>La cartera también se almacenará en este directorio.</translation>
</message>
<message>
<source>Error: Specified data directory "%1" cannot be created.</source>
@@ -1039,11 +1085,11 @@
</message>
<message>
<source>Last block time</source>
- <translation>Hora del último bloque.</translation>
+ <translation>Hora del último bloque</translation>
</message>
<message>
<source>Progress</source>
- <translation>Progreso.</translation>
+ <translation>Progreso</translation>
</message>
<message>
<source>Progress increase per hour</source>
@@ -1093,7 +1139,7 @@
</message>
<message>
<source>Open wallet warning</source>
- <translation>Aviso de apertura de monedero</translation>
+ <translation>Ver aviso sobre la cartera</translation>
</message>
<message>
<source>default wallet</source>
@@ -1139,16 +1185,12 @@
<translation>Muestra si el proxy SOCKS5 suministrado se utiliza para llegar a los pares a través de este tipo de red.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use SOCKS&amp;5 y proxy por separado para llegar a sus compañeros a través de los servicios ocultos de Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Ocultar el icono de la bandeja del sistema.</translation>
</message>
<message>
<source>&amp;Hide tray icon</source>
- <translation>Ocultar icono de bandeja</translation>
+ <translation>&amp;Ocultar el icono de la bandeja</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>
@@ -1204,7 +1246,7 @@
</message>
<message>
<source>W&amp;allet</source>
- <translation>Monedero</translation>
+ <translation>C&amp;artera</translation>
</message>
<message>
<source>Expert</source>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conéctese a la red de Bitcoin a través de un proxy SOCKS5 separado para los servicios Tor ocultos.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Ventana</translation>
</message>
@@ -1319,6 +1357,14 @@
<translation>Mostrar o no características de control de moneda</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Conéctese a la red de Bitcoin a través de un proxy SOCKS5 separado para los servicios Tor ocultos.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Usar proxy SOCKS&amp;5 para alcanzar nodos via servicios ocultos Tor:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>URLs de transacciones de terceros</translation>
</message>
@@ -1328,7 +1374,7 @@
</message>
<message>
<source>&amp;OK</source>
- <translation>&amp;Aceptar</translation>
+ <translation>&amp;OK</translation>
</message>
<message>
<source>&amp;Cancel</source>
@@ -1453,6 +1499,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Saldo total actual en direcciones de solo-ver</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>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>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialogo</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Firmar Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Emitir Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Copiar al portapapeles</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Guardar...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Cerrar</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Error en la carga de la transacción: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Error en la firma de la transacción: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>No se han podido firmar más entradas.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Se han firmado %1 entradas, pero aún se requieren más firmas.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Se ha firmado correctamente. La transacción está lista para difundirse.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Error desconocido al procesar la transacción.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>¡La transacción se ha difundido correctamente! Código ID de la transacción: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Ha habido un error en la difusión de la transacción: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT copiado al portapapeles</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Guardar datos de la transacción</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transacción firmada de manera parcial (Binaria) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT guardado en la memoria.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>* Envia %1 a %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>No se ha podido calcular la comisión por transacción o la totalidad de la cantidad de la transacción.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Pagar comisión de transacción:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Monto total</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>La transacción tiene %1 entradas no firmadas.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Le falta alguna información sobre entradas a la transacción.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>La transacción aún necesita firma(s).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Este monedero no puede firmar transacciones.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Este monedero no tiene las claves adecuadas.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>La transacción se ha firmado correctamente y está lista para difundirse.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>El estatus de la transacción es desconocido.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1717,10 +1890,6 @@
<translation>Cadena de bloques</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Número actual de bloques</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Grupo de memoria</translation>
</message>
@@ -1765,10 +1934,6 @@
<translation>Seleccione un par para ver información detallada.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Incluido en la lista blanca</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Dirección</translation>
</message>
@@ -1805,6 +1970,10 @@
<translation>Ventana de nodo</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>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>Abrir el archivo de depuración %1 desde el directorio de datos actual. Puede tardar unos segundos para ficheros de gran tamaño.</translation>
</message>
@@ -1817,12 +1986,12 @@
<translation>Aumentar el tamaño de la fuente</translation>
</message>
<message>
- <source>Services</source>
- <translation>Servicios</translation>
+ <source>Permissions</source>
+ <translation>Permisos</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Puntuación Ban</translation>
+ <source>Services</source>
+ <translation>Servicios</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2142,6 @@
<translation>Salida</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Sí</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Desconocido</translation>
</message>
@@ -2079,56 +2240,60 @@
<source>Copy amount</source>
<translation>Copiar cantidad</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear el monedero.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>No se ha podido generar una nueva dirección %1</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Código QR</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Copiar &amp;URI</translation>
+ <source>Request payment to ...</source>
+ <translation>Solicitar pago a...</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Copiar &amp;Dirección</translation>
+ <source>Address:</source>
+ <translation>Dirección:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>Guardar Imagen...</translation>
+ <source>Amount:</source>
+ <translation>Cantidad:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Solicitar pago a %1</translation>
+ <source>Label:</source>
+ <translation>Etiqueta:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Información del pago</translation>
+ <source>Message:</source>
+ <translation>Mensaje:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Monedero:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Dirección</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copiar &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Cantidad</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Copiar &amp;Dirección</translation>
</message>
<message>
- <source>Label</source>
- <translation>Etiqueta</translation>
+ <source>&amp;Save Image...</source>
+ <translation>Guardar Imagen...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Mensaje</translation>
+ <source>Request payment to %1</source>
+ <translation>Solicitar pago a %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Monedero</translation>
+ <source>Payment information</source>
+ <translation>Información del pago</translation>
</message>
</context>
<context>
@@ -2373,6 +2538,22 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>¿Seguro que quiere enviar?</translation>
</message>
<message>
+ <source>Create Unsigned</source>
+ <translation>Crear sin firmar</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Guardar datos de la transacción</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transacción firmaa de manera parcial (Binaria) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT guardado </translation>
+ </message>
+ <message>
<source>or</source>
<translation>o</translation>
</message>
@@ -2409,18 +2590,10 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Confirme la propuesta de transaccion</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copiar la TBPF al portapapeles</translation>
- </message>
- <message>
<source>Send</source>
<translation>Enviar</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>TBPF copiada</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Visualización unicamente balance:</translation>
</message>
@@ -3202,12 +3375,28 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>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>Cerrar todas las carteras</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>¿Está seguro de que desea cerrar todos los monederos?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No se ha cargado ningún monedero</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>No se ha cargado ningún monedero.
+Vaya a Archivo&gt; Abrir monedero para cargar un monedero.
+- O -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Crear monedero nuevo</translation>
</message>
</context>
<context>
@@ -3280,6 +3469,26 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Exportar a un archivo los datos de esta pestaña</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Cargar datos de la transacción</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Transacción firmada de manera parcial (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>El archivo PSBT debe ser más pequeño de 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Imposible descodificar PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Respaldar monedero</translation>
</message>
@@ -3323,10 +3532,6 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>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>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: Un error interno fatal ha ocurrido. Ver debug.log para detalles</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Poda blockstore...</translation>
</message>
@@ -3339,10 +3544,6 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Los desarrolladores de %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>No se puede generar una clave de cambio-de-dirección. No hay claves en el conjunto de claves internas y no se pueden generar claves.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>No se puede bloquear el directorio %s. %s probablemente ya se está ejecutando.</translation>
</message>
@@ -3391,14 +3592,6 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Advertencia: ¡No parecemos concordar del todo con nuestros pares! Puede que necesite actualizarse, o puede que otros nodos necesiten actualizarse.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d de los últimos 100 bloques tienen una versión no esperada</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupto. Fracasó la recuperación</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool debe ser por lo menos de %d MB</translation>
</message>
@@ -3475,6 +3668,10 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Fallo al escanear el monedero durante la inicialización</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>No se ha podido verificar la base de datos</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importando...</translation>
</message>
@@ -3523,10 +3720,6 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Cargando direcciones P2P...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Error: ¡Espacio en disco muy bajo!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Cargando banlist...</translation>
</message>
@@ -3603,6 +3796,14 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Necesita reconstruir la base de datos utilizando -reindex para volver al modo sin recorte. Esto volverá a descargar toda la cadena de bloques</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Ha ocurrido un error interno grave. Consulte debug.log para más detalles.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>¡El espacio en el disco es demasiado bajo!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Error al leer la base de datos, cerrando la aplicación.</translation>
</message>
@@ -3635,6 +3836,10 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Necesita especificar un puerto con -whitebind: '%s'</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>No se ha especificado un servidor de proxy. Use -proxy=&lt;ip&gt;o -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>El modo de poda es incompatible con -blockfilterindex</translation>
</message>
@@ -3709,10 +3914,6 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Advertencia: nuevas reglas desconocidas activadas (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Eliminando todas las transacciones del monedero...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee tiene un valor muy elevado. Comisiones muy grandes podrían ser pagadas en una única transacción.</translation>
</message>
@@ -3725,10 +3926,6 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>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>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Advertencia: ¡Archivo de monedero corrupto, datos recuperados! Original %s guardado como %s en %s; si su balance de transacciones es incorrecto, debe restaurar desde una copia de seguridad.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>¡%s está configurado muy alto!</translation>
</message>
@@ -3773,10 +3970,6 @@ Nota: Dado que la comisión se calcula por byte, una comisión de "100 satoshis
<translation>Fondos insuficientes</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>No se puede actualizar un monedero dividido sin HD sin actualizar para admitir el keypool pre dividido. Utilice -upgradewallet = 169900 o -upgradewallet sin una versión especificada.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Estimación de la comisión fallida. Fallbackfee está deshabilitado. Espere unos pocos bloques o habilite -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_CL.ts b/src/qt/locale/bitcoin_es_CL.ts
index 265eeeb2f7..3eb03c966e 100644
--- a/src/qt/locale/bitcoin_es_CL.ts
+++ b/src/qt/locale/bitcoin_es_CL.ts
@@ -542,11 +542,7 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>La billetera está &lt;b&gt; encriptada &lt;/ b&gt; y actualmente está &lt;b&gt; bloqueada &lt;/ b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Se produjo un error fatal. Bitcoin ya no puede continuar de manera segura y no continuará</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -956,10 +952,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Muestra si el proxy SOCKS5 suministrado se utiliza para llegar a los pares a través de este tipo de red.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use SOCKS&amp;5 y proxy por separado para llegar a sus compañeros a través de los servicios ocultos de Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Ocultar el icono de la bandeja del sistema.</translation>
</message>
@@ -1072,10 +1064,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conéctese a la red de Bitcoin a través de un proxy SOCKS5 separado para los servicios Tor ocultos.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>Ventana</translation>
</message>
@@ -1246,7 +1234,18 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<source>Current total balance in watch-only addresses</source>
<translation>Saldo total actual en direcciones de solo reloj</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Cambiar contraseña</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1470,10 +1469,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Cadena de bloques</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Número actual de bloques</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Grupo de memoria</translation>
</message>
@@ -1510,10 +1505,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Seleccione un par para ver información detallada.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Incluido en la lista blanca</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Dirección</translation>
</message>
@@ -1550,10 +1541,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Servicios</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Puntuación Ban</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Tiempo de conexión</translation>
</message>
@@ -1694,14 +1681,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Salida</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Si</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Desconocido</translation>
</message>
@@ -1780,12 +1759,28 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<source>Copy amount</source>
<translation>Copiar cantidad</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear la billetera.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Código QR</translation>
+ <source>Amount:</source>
+ <translation>Cantidad:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Etiqueta</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mensaje:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Billetera:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1807,30 +1802,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<source>Payment information</source>
<translation>Información del pago</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Dirección</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidad</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensaje</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Billetera</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2715,11 +2686,7 @@ Tarifa de copia</translation>
</context>
<context>
<name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>No se ha cargado ningún monedero</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletModel</name>
<message>
@@ -2775,6 +2742,10 @@ Tarifa de copia</translation>
Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Respaldar monedero</translation>
</message>
@@ -2810,10 +2781,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>La Poda se ha configurado por debajo del mínimo de %d MiB. Por favor utiliza un valor mas alto.</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: Un error interno fatal ha ocurrido, ver debug.log para detalles</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Poda blockstore...</translation>
</message>
@@ -2830,14 +2797,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Esta es la cuota de transacción que puede descartar si el cambio es más pequeño que el polvo a este nivel.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d de los últimos 100 bloques tienen una versión no esperada</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupto. Fracasó la recuperación</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool debe ser por lo menos de %d MB</translation>
</message>
@@ -3018,10 +2977,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>Advertencia: nuevas reglas desconocidas activadas (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Eliminando todas las transacciones del monedero...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee tiene un valor muy elevado! Comisiones muy grandes podrían ser pagadas en una única transacción.</translation>
</message>
@@ -3034,10 +2989,6 @@ Exportar los datos en la pestaña actual a un archivo</translation>
<translation>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>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Advertencia: Archivo de monedero corrupto, datos recuperados! Original %s guardado como %s en %s; si su balance de transacciones es incorrecto, debe restaurar desde una copia de seguridad.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>¡%s esta configurado muy alto!</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_CO.ts b/src/qt/locale/bitcoin_es_CO.ts
index 751dd5ca5b..fd47d5103f 100644
--- a/src/qt/locale/bitcoin_es_CO.ts
+++ b/src/qt/locale/bitcoin_es_CO.ts
@@ -537,11 +537,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>La billetera esta &lt;b&gt;codificada&lt;/b&gt; y actualmente &lt;b&gt;bloqueda&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Ha ocurrido un error fatal. Bitcoin no puede seguir seguro y se cerrará.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -960,10 +956,6 @@
<translation>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>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use SOCKS&amp;5 y proxy por separado para llegar a sus compañeros a través de los servicios ocultos de Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Ocultar el icono de la bandeja del sistema.</translation>
</message>
@@ -1076,10 +1068,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conectar a la red de Bitcoin a través de un proxy SOCKS5 diferente para los servicios anónimos de Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>y windows
</translation>
@@ -1251,7 +1239,14 @@
<source>Current total balance in watch-only addresses</source>
<translation>Saldo total actual en direcciones de solo reloj</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1475,10 +1470,6 @@
<translation>Bloquea cadena</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Cantidad de bloques actual</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1515,10 +1506,6 @@
<translation>Selecciona un peer para ver la información detallada.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>En la lista blanca</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Dirección</translation>
</message>
@@ -1556,10 +1543,6 @@
<translation>Servicios</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Puntuación de bloqueo</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Duración de la conexión</translation>
</message>
@@ -1700,14 +1683,6 @@
<translation>Saliente</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Si</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Desconocido</translation>
</message>
@@ -1786,12 +1761,24 @@
<source>Copy amount</source>
<translation>Copiar Cantidad</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear la billetera.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Código QR</translation>
+ <source>Amount:</source>
+ <translation>Cantidad:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mensaje:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Billetera:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1813,30 +1800,6 @@
<source>Payment information</source>
<translation>Información del pago</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Dirección</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidad</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensaje</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Cartera</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2721,11 +2684,7 @@
</context>
<context>
<name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>No se ha cargado ningún monedero</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletModel</name>
<message>
@@ -2780,6 +2739,10 @@
<translation>Exportar los datos de la pestaña actual a un archivo</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Respaldar monedero</translation>
</message>
@@ -2815,10 +2778,6 @@
<translation>La Poda se ha configurado por debajo del mínimo de %d MiB. Por favor utiliza un valor mas alto.</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: Un error interno fatal ha ocurrido, ver debug.log para detalles</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Poda blockstore...</translation>
</message>
@@ -2835,14 +2794,6 @@
<translation>Esta es la cuota de transacción que puede descartar si el cambio es más pequeño que el polvo a este nivel.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d de los últimos 100 bloques tienen una versión no esperada</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupto. Fracasó la recuperación</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool debe ser por lo menos de %d MB</translation>
</message>
@@ -3023,10 +2974,6 @@
<translation>Advertencia: nuevas reglas desconocidas activadas (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Eliminando todas las transacciones del monedero...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee tiene un valor muy elevado! Comisiones muy grandes podrían ser pagadas en una única transacción.</translation>
</message>
@@ -3039,10 +2986,6 @@
<translation>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>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Advertencia: Archivo de monedero corrupto, datos recuperados! Original %s guardado como %s en %s; si su balance de transacciones es incorrecto, debe restaurar desde una copia de seguridad.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>¡%s esta configurado muy alto!</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_DO.ts b/src/qt/locale/bitcoin_es_DO.ts
index af7b5189b6..561974f4c8 100644
--- a/src/qt/locale/bitcoin_es_DO.ts
+++ b/src/qt/locale/bitcoin_es_DO.ts
@@ -407,11 +407,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>La billetera está encriptada y bloqueada recientemente</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Ha ocurrido un error crítico. Bitcoin ya no puede continuar con seguridad y se cerrará.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -861,6 +857,13 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -995,10 +998,6 @@
<translation>Cadena de bloques</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Número actual de bloques</translation>
- </message>
- <message>
<source>Last block time</source>
<translation>Hora del último bloque</translation>
</message>
@@ -1081,12 +1080,20 @@
<source>Copy amount</source>
<translation>Copiar cantidad</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear el monedero.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Código QR</translation>
+ <source>Amount:</source>
+ <translation>Monto:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mensaje:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1108,30 +1115,6 @@
<source>Payment information</source>
<translation>Información de pago</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Direccion</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Monto</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Nombre</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensaje</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Billetera</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1839,11 +1822,7 @@
</context>
<context>
<name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>No se ha cargado ningún monedero</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletModel</name>
<message>
@@ -1862,6 +1841,10 @@
<translation>Exportar los datos en la pestaña actual a un archivo</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Respaldo de monedero</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_MX.ts b/src/qt/locale/bitcoin_es_MX.ts
index 2c0028debc..c045a23262 100644
--- a/src/qt/locale/bitcoin_es_MX.ts
+++ b/src/qt/locale/bitcoin_es_MX.ts
@@ -70,8 +70,10 @@
<translation>Estas son tus direcciones de Bitcoin para enviar pagos. Siempre revisa el monto y la dirección de envío antes de enviar 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.</source>
- <translation>Estas son tus direcciones Bitcoin para recibir pagos. Usa el botón "Crear Nueva Dirección de Recepción" en la pestaña de recepciones para crear nuevas direcciones.</translation>
+ <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>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>
@@ -440,6 +442,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<source>&amp;Command-line options</source>
<translation>opciones de la &amp;Linea de comandos</translation>
</message>
+ <message numerus="yes">
+ <source>%n active connection(s) to Bitcoin network</source>
+ <translation><numerusform>%n active connection to Bitcoin network</numerusform><numerusform>%n active connections to Bitcoin network</numerusform></translation>
+ </message>
<message>
<source>Indexing blocks on disk...</source>
<translation>Indexando bloques en el disco...</translation>
@@ -448,6 +454,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<source>Processing blocks on disk...</source>
<translation>Procesando bloques en el disco...</translation>
</message>
+ <message numerus="yes">
+ <source>Processed %n block(s) of transaction history.</source>
+ <translation><numerusform>Processed %n block of transaction history.</numerusform><numerusform>Processed %n blocks of transaction history.</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 behind</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Last received block was generated %1 ago.</translation>
+ </message>
<message>
<source>Transactions after this will not yet be visible.</source>
<translation>Las transacciones después de esto todavía no serán visibles.</translation>
@@ -469,6 +487,42 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Actualizado al dia </translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Load PSBT from file...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Load Partially Signed Bitcoin Transaction</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Load PSBT from clipboard...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Load Partially Signed Bitcoin Transaction from clipboard</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation>Node window</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Open node debugging and diagnostic console</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation>&amp;Sending addresses</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation>&amp;Receiving addresses</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Open a bitcoin: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Abrir Cartera</translation>
</message>
@@ -485,6 +539,26 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Cerrar cartera</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Close All Wallets...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Close all wallets</translation>
+ </message>
+ <message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Show the %1 help message to get a list with possible Bitcoin command-line options</translation>
+ </message>
+ <message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Mask values</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Mask the values in the Overview tab</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>cartera predeterminada</translation>
</message>
@@ -501,10 +575,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Minimizar</translation>
</message>
<message>
+ <source>Zoom</source>
+ <translation>Zoom</translation>
+ </message>
+ <message>
<source>Main Window</source>
<translation>Ventana Principal</translation>
</message>
<message>
+ <source>%1 client</source>
+ <translation>%1 client</translation>
+ </message>
+ <message>
<source>Connecting to peers...</source>
<translation>Conectando con los compañeros...</translation>
</message>
@@ -527,6 +609,36 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
</translation>
</message>
<message>
+ <source>Amount: %1
+</source>
+ <translation>Amount: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Wallet: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Type: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Label: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Address: %1
+</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>Enviar Transacción</translation>
</message>
@@ -535,6 +647,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Transacción entrante</translation>
</message>
<message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Private key &lt;b&gt;disabled&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>La cartera esta &lt;b&gt;encriptada&lt;/b&gt; y &lt;b&gt;desbloqueada&lt;/b&gt; actualmente </translation>
</message>
@@ -543,8 +667,12 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>La cartera esta &lt;b&gt;encriptada&lt;/b&gt; y &lt;b&gt;bloqueada&lt;/b&gt; actualmente </translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Se produjo un error fatal. Bitcoin ya no puede continuar de forma segura y va a renunciar.</translation>
+ <source>Original message:</source>
+ <translation>Original message:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>A fatal error occurred. %1 can no longer continue safely and will quit.</translation>
</message>
</context>
<context>
@@ -634,6 +762,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Copiar identificación de la transacción. </translation>
</message>
<message>
+ <source>Lock unspent</source>
+ <translation>Lock unspent</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Unlock unspent</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>Copiar cantidad</translation>
</message>
@@ -650,10 +786,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Copiar bytes</translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>Copy dust</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>Copiar cambio</translation>
</message>
<message>
+ <source>(%1 locked)</source>
+ <translation>(%1 locked)</translation>
+ </message>
+ <message>
<source>yes</source>
<translation>si</translation>
</message>
@@ -666,10 +810,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>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>Can vary +/- %1 satoshi(s) per input.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
<message>
+ <source>change from %1 (%2)</source>
+ <translation>change from %1 (%2)</translation>
+ </message>
+ <message>
<source>(change)</source>
<translation>cambio</translation>
</message>
@@ -677,6 +829,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<context>
<name>CreateWalletActivity</name>
<message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
<source>Create wallet failed</source>
<translation>La creación de la cartera falló</translation>
</message>
@@ -712,6 +868,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Desactivar 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>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>Make Blank Wallet</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Use descriptors for scriptPubKey management</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Descriptor Wallet</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Crear</translation>
</message>
@@ -751,6 +923,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Editar dirección de envío</translation>
</message>
<message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>The entered address "%1" is not a 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>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>The entered address "%1" is already in the address book with label "%2".</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation>No se puede desbloquear la cartera</translation>
</message>
@@ -770,6 +954,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>nombre</translation>
</message>
<message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Directory already exists. Add %1 if you intend to create a new directory here.</translation>
+ </message>
+ <message>
<source>Path already exists, and is not a directory.</source>
<translation>El camino ya existe, y no es un directorio.</translation>
</message>
@@ -785,6 +973,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>versión</translation>
</message>
<message>
+ <source>About %1</source>
+ <translation>About %1</translation>
+ </message>
+ <message>
<source>Command-line options</source>
<translation>opciones de la Linea de comandos</translation>
</message>
@@ -796,6 +988,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Bienvenido</translation>
</message>
<message>
+ <source>Welcome to %1.</source>
+ <translation>Welcome to %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>As this is the first time the program is launched, you can choose where %1 will store its 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>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.</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>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>
@@ -804,6 +1008,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>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>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>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>Usar el directorio de datos predeterminado</translation>
</message>
@@ -816,14 +1024,46 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Discard blocks after verification, except most recent %1 GB (prune)</translation>
+ </message>
+ <message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>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>Approximately %1 GB of data will be stored in this directory.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 will download and store a copy of the Bitcoin block chain.</translation>
+ </message>
+ <message>
<source>The wallet will also be stored in this directory.</source>
<translation>La cartera también se almacenará en este directorio.</translation>
</message>
<message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Error: Specified data directory "%1" cannot be created.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Error</translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>%n GB of free space available</source>
+ <translation><numerusform>%n GB of free space available</numerusform><numerusform>%n GB of free space available</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(of %n GB needed)</numerusform><numerusform>(of %n GB needed)</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB needed for full chain)</numerusform><numerusform>(%n GB needed for full chain)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -847,6 +1087,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Desconocido...</translation>
</message>
<message>
+ <source>Last block time</source>
+ <translation>Last block time</translation>
+ </message>
+ <message>
<source>Progress</source>
<translation>Progreso </translation>
</message>
@@ -870,7 +1114,15 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<source>Esc</source>
<translation>Esc</translation>
</message>
- </context>
+ <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>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>Unknown. Syncing Headers (%1, %2%)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -889,10 +1141,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Abrir la cartera falló</translation>
</message>
<message>
+ <source>Open wallet warning</source>
+ <translation>Open wallet warning</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>cartera predeterminada</translation>
</message>
- </context>
+ <message>
+ <source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+</context>
<context>
<name>OptionsDialog</name>
<message>
@@ -900,18 +1160,106 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Opciones</translation>
</message>
<message>
+ <source>&amp;Main</source>
+ <translation>&amp;Main</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Automatically start %1 after logging in to the system.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Start %1 on system login</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Size of &amp;database cache</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>Number of script &amp;verification threads</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>IP address of the proxy (e.g. 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>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Hide the icon from the system tray.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Hide tray icon</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>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>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>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 |.</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Open the %1 configuration file from the working directory.</translation>
+ </message>
+ <message>
<source>Open Configuration File</source>
<translation>Abrir Configuración de Archivo</translation>
</message>
<message>
+ <source>Reset all client options to default.</source>
+ <translation>Reset all client options to default.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;Reset Options</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;Network</translation>
+ </message>
+ <message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Prune &amp;block storage to</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Reverting this setting requires re-downloading the entire blockchain.</translation>
+ </message>
+ <message>
+ <source>MiB</source>
+ <translation>MiB</translation>
+ </message>
+ <message>
+ <source>(0 = auto, &lt;0 = leave that many cores free)</source>
+ <translation>(0 = auto, &lt;0 = leave that many cores free)</translation>
+ </message>
+ <message>
<source>W&amp;allet</source>
<translation>Cartera</translation>
</message>
<message>
+ <source>Expert</source>
+ <translation>Expert</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Enable coin &amp;control features</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>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>
@@ -920,43 +1268,430 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>&amp;Gastar el cambio no confirmado</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>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation>Map port using &amp;UPnP</translation>
+ </message>
+ <message>
<source>Accept connections from outside.</source>
<translation>Aceptar las conexiones del exterior.</translation>
</message>
<message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Allow incomin&amp;g connections</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>Connect to the Bitcoin network through a SOCKS5 proxy.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Connect through SOCKS5 proxy (default proxy):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>Proxy &amp;IP:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;Port:</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation>Port of the proxy (e.g. 9050)</translation>
+ </message>
+ <message>
+ <source>Used for reaching peers via:</source>
+ <translation>Used for reaching peers via:</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Tor</translation>
+ </message>
+ <message>
<source>&amp;Window</source>
<translation>&amp;Ventana</translation>
</message>
<message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>Show only a tray icon after minimizing the window.</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation>&amp;Minimize to the tray instead of the taskbar</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>M&amp;inimize on close</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation>&amp;Display</translation>
+ </message>
+ <message>
<source>User Interface &amp;language:</source>
<translation>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>The user interface language can be set here. This setting will take effect after restarting %1.</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>&amp;Unit to show amounts in:</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation>Choose the default subdivision unit to show in the interface and when sending coins.</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Whether to show coin control features or not.</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</translation>
+ </message>
+ <message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;Third party transaction URLs</translation>
+ </message>
+ <message>
+ <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
+ <translation>Options set in this dialog are overridden by the command line or in the configuration file:</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>&amp;OK</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>&amp;Cancel</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>default</translation>
+ </message>
+ <message>
<source>none</source>
<translation>Ninguno </translation>
</message>
<message>
+ <source>Confirm options reset</source>
+ <translation>Confirm options reset</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Client restart required to activate changes.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Client will be shut down. Do you want to proceed?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Configuration options</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>
+ <translation>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
+ <source>The configuration file could not be opened.</source>
+ <translation>The configuration file could not be opened.</translation>
+ </message>
+ <message>
<source>This change would require a client restart.</source>
<translation>Este cambio requeriría un reinicio del cliente.</translation>
</message>
- </context>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>The supplied proxy address is invalid.</translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
<message>
<source>Form</source>
<translation>Formulario</translation>
</message>
- </context>
+ <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>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.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Watch-only:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Available:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Your current spendable balance</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Pending:</translation>
+ </message>
+ <message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>Immature:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>Mined balance that has not yet matured</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>Balances</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Total:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>Your current total balance</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>Your current balance in watch-only addresses</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Spendable:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>&lt;b&gt;Transacciones recientes&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>Unconfirmed transactions to watch-only addresses</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>Mined balance in watch-only addresses that has not yet matured</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>Current total balance in watch-only addresses</translation>
+ </message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Sign Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Broadcast Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Copy to Clipboard</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Save...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Close</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Failed to load transaction: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Failed to sign transaction: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Could not sign any more inputs.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Signed %1 inputs, but more signatures are still required.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Signed transaction successfully. Transaction is ready to broadcast.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Unknown error processing transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Transaction broadcast successfully! Transaction ID: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Transaction broadcast failed: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT copied to clipboard.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Save Transaction Data</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Partially Signed Transaction (Binary) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT saved to disk.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation> * Sends %1 to %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Unable to calculate transaction fee or total transaction amount.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Pays transaction fee: </translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Cantidad total</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Transaction has %1 unsigned inputs.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Transaction is missing some information about inputs.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Transaction still needs signature(s).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(But this wallet cannot sign transactions.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(But this wallet does not have the right keys.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Transaction is fully signed and ready for broadcast.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Transaction status is unknown.</translation>
+ </message>
+</context>
<context>
<name>PaymentServer</name>
- </context>
+ <message>
+ <source>Payment request error</source>
+ <translation>Payment request error</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Cannot start bitcoin: click-to-pay handler</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>URI handling</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</translation>
+ </message>
+ <message>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Cannot process payment request because BIP70 is not supported.</translation>
+ </message>
+ <message>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</translation>
+ </message>
+ <message>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Invalid payment address %1</translation>
+ </message>
+ <message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Payment request file handling</translation>
+ </message>
+</context>
<context>
<name>PeerTableModel</name>
<message>
+ <source>User Agent</source>
+ <translation>User Agent</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>Node/Service</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>NodeId</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
<source>Sent</source>
<translation>Enviado</translation>
</message>
@@ -972,14 +1707,102 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Monto</translation>
</message>
<message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Enter a Bitcoin address (e.g. %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 d</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 h</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 m</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 s</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>None</translation>
+ </message>
+ <message>
<source>N/A</source>
<translation>N/A</translation>
</message>
<message>
+ <source>%1 ms</source>
+ <translation>%1 ms</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n second(s)</source>
+ <translation><numerusform>%n second</numerusform><numerusform>%n seconds</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n minute(s)</source>
+ <translation><numerusform>%n minute</numerusform><numerusform>%n minutes</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n hour(s)</source>
+ <translation><numerusform>%n hour</numerusform><numerusform>%n hours</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n day(s)</source>
+ <translation><numerusform>%n day</numerusform><numerusform>%n days</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>%n week(s)</source>
+ <translation><numerusform>%n week</numerusform><numerusform>%n weeks</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 and %2</source>
+ <translation>%1 and %2</translation>
+ </message>
+ <message numerus="yes">
+ <source>%n year(s)</source>
+ <translation><numerusform>%n year</numerusform><numerusform>%n years</numerusform></translation>
+ </message>
+ <message>
+ <source>%1 B</source>
+ <translation>%1 B</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 KB</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 MB</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 GB</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Error: Specified data directory "%1" does not exist.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Error: Cannot parse configuration file: %1.</translation>
+ </message>
+ <message>
<source>Error: %1</source>
<translation>Error: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Error initializing settings: %1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 didn't yet exit safely...</translation>
+ </message>
+ <message>
<source>unknown</source>
<translation>desconocido</translation>
</message>
@@ -995,6 +1818,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>&amp;Copiar Imagen</translation>
</message>
<message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>Resulting URI too long, try to reduce the text for label / message.</translation>
+ </message>
+ <message>
<source>Error encoding URI into QR Code.</source>
<translation>Error codificando la URI en el Código QR.</translation>
</message>
@@ -1030,6 +1857,30 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>General</translation>
</message>
<message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Using BerkeleyDB version</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>Datadir</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the data directory use the '%1' option.</source>
+ <translation>To specify a non-default location of the data directory use the '%1' option.</translation>
+ </message>
+ <message>
+ <source>Blocksdir</source>
+ <translation>Blocksdir</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the blocks directory use the '%1' option.</source>
+ <translation>To specify a non-default location of the blocks directory use the '%1' option.</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>Startup time</translation>
+ </message>
+ <message>
<source>Network</source>
<translation>Red</translation>
</message>
@@ -1038,6 +1889,26 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Nombre</translation>
</message>
<message>
+ <source>Number of connections</source>
+ <translation>Number of connections</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation>Block chain</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation>Memory Pool</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Current number of transactions</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Memory usage</translation>
+ </message>
+ <message>
<source>Wallet: </source>
<translation>Cartera:</translation>
</message>
@@ -1046,6 +1917,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>(ninguno)</translation>
</message>
<message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Reset</translation>
+ </message>
+ <message>
<source>Received</source>
<translation>Recibido</translation>
</message>
@@ -1054,6 +1929,62 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Enviado</translation>
</message>
<message>
+ <source>&amp;Peers</source>
+ <translation>&amp;Peers</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>Banned peers</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>Select a peer to view detailed information.</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Direction</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>Version</translation>
+ </message>
+ <message>
+ <source>Starting Block</source>
+ <translation>Starting Block</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation>Synced Headers</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Synced Blocks</translation>
+ </message>
+ <message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation>The mapped Autonomous System used for diversifying peer selection.</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation>Mapped AS</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>User Agent</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation>Node window</translation>
+ </message>
+ <message>
+ <source>Current block height</source>
+ <translation>Current block height</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>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>Reducir el tamaño de la letra</translation>
</message>
@@ -1062,6 +1993,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Aumentar el tamaño de la letra</translation>
</message>
<message>
+ <source>Permissions</source>
+ <translation>Permissions</translation>
+ </message>
+ <message>
<source>Services</source>
<translation>Servicios</translation>
</message>
@@ -1078,6 +2013,110 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Última recepción</translation>
</message>
<message>
+ <source>Ping Time</source>
+ <translation>Ping Time</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation>The duration of a currently outstanding ping.</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>Ping Wait</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>Min Ping</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>Time Offset</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Last block time</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>&amp;Open</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation>&amp;Console</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;Network Traffic</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation>Totals</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>In:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Out:</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation>Debug log file</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>Clear console</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;hour</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;day</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;week</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;year</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Disconnect</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Ban for</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Unban</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Welcome to the %1 RPC console.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Use up and down arrows to navigate history, and %1 to clear screen.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Type %1 for an overview of available commands.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>For more information on using this console type %1.</translation>
+ </message>
+ <message>
+ <source>WARNING: 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.</source>
+ <translation>WARNING: 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.</translation>
+ </message>
+ <message>
<source>Network activity disabled</source>
<translation>Actividad de la red desactivada</translation>
</message>
@@ -1086,6 +2125,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Ejecutando el comando sin ninguna cartera</translation>
</message>
<message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Executing command using "%1" wallet</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(node id: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>via %1</translation>
+ </message>
+ <message>
<source>never</source>
<translation>nunca</translation>
</message>
@@ -1098,14 +2149,6 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Salida</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Sí</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Desconocido</translation>
</message>
@@ -1161,6 +2204,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Borrar </translation>
</message>
<message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generate native segwit (Bech32) address</translation>
+ </message>
+ <message>
<source>Requested payments history</source>
<translation>Historial de pagos solicitados</translation>
</message>
@@ -1181,43 +2232,75 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Eliminar </translation>
</message>
<message>
+ <source>Copy URI</source>
+ <translation>Copy URI</translation>
+ </message>
+ <message>
<source>Copy label</source>
<translation>Copiar capa </translation>
</message>
<message>
+ <source>Copy message</source>
+ <translation>Copy message</translation>
+ </message>
+ <message>
<source>Copy amount</source>
<translation>copiar monto</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se puede desbloquear la cartera</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Could not generate new %1 address</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Copiar dirección</translation>
+ <source>Request payment to ...</source>
+ <translation>Request payment to ...</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Guardar imagen...</translation>
+ <source>Address:</source>
+ <translation>Address:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Dirección</translation>
+ <source>Amount:</source>
+ <translation>Monto:</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Monto</translation>
+ <source>Label:</source>
+ <translation>Label:</translation>
</message>
<message>
- <source>Label</source>
- <translation>Etiqueta</translation>
+ <source>Message:</source>
+ <translation>Mensaje:</translation>
</message>
<message>
- <source>Message</source>
- <translation>Mensaje</translation>
+ <source>Wallet:</source>
+ <translation>Cartera:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Cartera</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copy &amp;URI</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Copiar dirección</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Guardar imagen...</translation>
+ </message>
+ <message>
+ <source>Request payment to %1</source>
+ <translation>Request payment to %1</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Payment information</translation>
</message>
</context>
<context>
@@ -1238,7 +2321,19 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation>(no message)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(no amount requested)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Requested</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
@@ -1246,6 +2341,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Enviar monedas</translation>
</message>
<message>
+ <source>Coin Control Features</source>
+ <translation>Coin Control Features</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>Inputs...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>automatically selected</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>Insufficient funds!</translation>
+ </message>
+ <message>
<source>Quantity:</source>
<translation>Cantidad</translation>
</message>
@@ -1270,14 +2381,66 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>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>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>Custom change address</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>Transaction Fee:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>Choose...</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>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.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Warning: Fee estimation is currently not possible.</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 of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>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 of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
+ </message>
+ <message>
<source>Hide</source>
<translation>Ocultar </translation>
</message>
<message>
+ <source>Recommended:</source>
+ <translation>Recommended:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Custom:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Smart fee not initialized yet. This usually takes a few blocks...)</translation>
+ </message>
+ <message>
<source>Send to multiple recipients at once</source>
<translation>Enviar a múltiples receptores a la vez</translation>
</message>
<message>
+ <source>Add &amp;Recipient</source>
+ <translation>Add &amp;Recipient</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Despeja todos los campos del formulario.</translation>
</message>
@@ -1286,6 +2449,34 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Remanente monetario:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Hide transaction fee settings</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>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.</translation>
+ </message>
+ <message>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation>A too low fee might result in a never confirming transaction (read the tooltip)</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Confirmation time target:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Enable 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>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.</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Clear &amp;All</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation>Saldo:</translation>
</message>
@@ -1294,6 +2485,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Confirme la acción de enviar</translation>
</message>
<message>
+ <source>S&amp;end</source>
+ <translation>S&amp;end</translation>
+ </message>
+ <message>
<source>Copy quantity</source>
<translation>Copiar cantidad</translation>
</message>
@@ -1314,10 +2509,38 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Copiar bytes</translation>
</message>
<message>
+ <source>Copy dust</source>
+ <translation>Copy dust</translation>
+ </message>
+ <message>
<source>Copy change</source>
<translation>Copiar cambio</translation>
</message>
<message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blocks)</translation>
+ </message>
+ <message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Cr&amp;eate Unsigned</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>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation> from wallet '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 to '%2'</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 to %2</translation>
+ </message>
+ <message>
<source>Do you want to draft this transaction?</source>
<translation>¿Quiere redactar esta transacción?</translation>
</message>
@@ -1326,10 +2549,34 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>¿Está seguro de que quiere enviar?</translation>
</message>
<message>
+ <source>Create Unsigned</source>
+ <translation>Create Unsigned</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Save Transaction Data</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Partially Signed Transaction (Binary) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT saved</translation>
+ </message>
+ <message>
<source>or</source>
<translation>o</translation>
</message>
<message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>You can increase the fee later (signals 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>
+ <translation>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.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Por favor, revise su transacción.</translation>
</message>
@@ -1338,6 +2585,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Cuota de transacción</translation>
</message>
<message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Not signalling Replace-By-Fee, BIP-125.</translation>
+ </message>
+ <message>
<source>Total Amount</source>
<translation>Cantidad total</translation>
</message>
@@ -1358,6 +2609,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Enviar</translation>
</message>
<message>
+ <source>Watch-only balance:</source>
+ <translation>Watch-only balance:</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>La dirección del destinatario no es válida. Por favor, vuelva a verificarla.</translation>
</message>
@@ -1370,6 +2625,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>La cantidad excede su saldo.</translation>
</message>
<message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>The total exceeds your balance when the %1 transaction fee is included.</translation>
+ </message>
+ <message>
<source>Duplicate address found: addresses should only be used once each.</source>
<translation>Duplicado de la dirección encontrada: las direcciones sólo deben ser utilizadas una vez cada una.</translation>
</message>
@@ -1378,9 +2637,17 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>¡La creación de la transación falló!</translation>
</message>
<message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>A fee higher than %1 is considered an absurdly high fee.</translation>
+ </message>
+ <message>
<source>Payment request expired.</source>
<translation>La solicitud de pago expiró.</translation>
</message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Estimated to begin confirmation within %n block.</numerusform><numerusform>Estimated to begin confirmation within %n blocks.</numerusform></translation>
+ </message>
<message>
<source>Warning: Invalid Bitcoin address</source>
<translation>Advertencia: Dirección de Bitcoin invalida</translation>
@@ -1394,6 +2661,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Confirmar la 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>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?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(sin etiqueta)</translation>
</message>
@@ -1437,6 +2708,18 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Quitar esta entrada</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>The amount to send in the selected unit</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>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.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>S&amp;ubtract fee from amount</translation>
+ </message>
+ <message>
<source>Use available balance</source>
<translation>Usar el saldo disponible</translation>
</message>
@@ -1457,13 +2740,25 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Introducir 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>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.</translation>
+ </message>
+ <message>
<source>Pay To:</source>
<translation>Pago para:</translation>
</message>
- </context>
+ <message>
+ <source>Memo:</source>
+ <translation>Memo:</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
<message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 is shutting down...</translation>
+ </message>
+ <message>
<source>Do not shut down the computer until this window disappears.</source>
<translation>No apague su computadora hasta que esta ventana desaparesca.</translation>
</message>
@@ -1471,6 +2766,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<context>
<name>SignVerifyMessageDialog</name>
<message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>Signatures - Sign / Verify a Message</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;Sign Message</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>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.</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>The Bitcoin address to sign the message with</translation>
+ </message>
+ <message>
<source>Choose previously used address</source>
<translation>Elegir la dirección utilizada anteriormente</translation>
</message>
@@ -1487,20 +2798,160 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Alt+P</translation>
</message>
<message>
+ <source>Enter the message you want to sign here</source>
+ <translation>Enter the message you want to sign here</translation>
+ </message>
+ <message>
<source>Signature</source>
<translation>Firma</translation>
</message>
- </context>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>Copy the current signature to the system clipboard</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation>Sign the message to prove you own this Bitcoin address</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>Sign &amp;Message</translation>
+ </message>
+ <message>
+ <source>Reset all sign message fields</source>
+ <translation>Reset all sign message fields</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Clear &amp;All</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;Verify Message</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>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!</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>The Bitcoin address the message was signed with</translation>
+ </message>
+ <message>
+ <source>The signed message to verify</source>
+ <translation>The signed message to verify</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>The signature given when the message was signed</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>Verify the message to ensure it was signed with the specified Bitcoin address</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation>Verify &amp;Message</translation>
+ </message>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation>Reset all verify message fields</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Click "Sign Message" to generate signature</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>The entered address is invalid.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Please check the address and try again.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>The entered address does not refer to a key.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Wallet unlock was cancelled.</translation>
+ </message>
+ <message>
+ <source>No error</source>
+ <translation>No error</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>Private key for the entered address is not available.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Message signing failed.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Message signed.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>The signature could not be decoded.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Please check the signature and try again.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>The signature did not match the message digest.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Message verification failed.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Message verified.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>KB/s</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Open for %n more block</numerusform><numerusform>Open for %n more blocks</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Abrir hasta %1</translation>
</message>
<message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>conflicted with a transaction with %1 confirmations</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/unconfirmed, %1</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>in memory pool</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>not in memory pool</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>abandoned</translation>
+ </message>
+ <message>
<source>%1/unconfirmed</source>
<translation>%1/No confirmado</translation>
</message>
@@ -1517,6 +2968,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Fecha</translation>
</message>
<message>
+ <source>Source</source>
+ <translation>Source</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Generated</translation>
+ </message>
+ <message>
<source>From</source>
<translation>De</translation>
</message>
@@ -1529,14 +2988,50 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Para</translation>
</message>
<message>
+ <source>own address</source>
+ <translation>own address</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>watch-only</translation>
+ </message>
+ <message>
<source>label</source>
<translation>etiqueta</translation>
</message>
<message>
+ <source>Credit</source>
+ <translation>Credit</translation>
+ </message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>matures in %n more block</numerusform><numerusform>matures in %n more blocks</numerusform></translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>not accepted</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Debit</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Total debit</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Total credit</translation>
+ </message>
+ <message>
<source>Transaction fee</source>
<translation>Cuota de transacción</translation>
</message>
<message>
+ <source>Net amount</source>
+ <translation>Net amount</translation>
+ </message>
+ <message>
<source>Message</source>
<translation>Mensaje</translation>
</message>
@@ -1549,21 +3044,65 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>ID</translation>
</message>
<message>
+ <source>Transaction total size</source>
+ <translation>Transaction total size</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation>Transaction virtual size</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>Output index</translation>
+ </message>
+ <message>
+ <source> (Certificate was not verified)</source>
+ <translation> (Certificate was not verified)</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Merchant</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>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.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Debug information</translation>
+ </message>
+ <message>
<source>Transaction</source>
<translation>Transacción</translation>
</message>
<message>
+ <source>Inputs</source>
+ <translation>Inputs</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Monto</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>true</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>false</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
<message>
<source>This pane shows a detailed description of the transaction</source>
<translation>Este panel muestras una descripción detallada de la transacción</translation>
</message>
- </context>
+ <message>
+ <source>Details for %1</source>
+ <translation>Details for %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
@@ -1578,15 +3117,39 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<source>Label</source>
<translation>Etiqueta</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>Open for %n more block</numerusform><numerusform>Open for %n more blocks</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>Abrir hasta %1</translation>
</message>
<message>
+ <source>Unconfirmed</source>
+ <translation>Unconfirmed</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>Abandoned</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Confirming (%1 of %2 recommended confirmations)</translation>
+ </message>
+ <message>
<source>Confirmed (%1 confirmations)</source>
<translation>Confimado (%1 confirmaciones)</translation>
</message>
<message>
+ <source>Conflicted</source>
+ <translation>Conflicted</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Immature (%1 confirmations, will be available after %2)</translation>
+ </message>
+ <message>
<source>Generated but not accepted</source>
<translation>Generado pero no aprovado</translation>
</message>
@@ -1595,6 +3158,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Recibido con</translation>
</message>
<message>
+ <source>Received from</source>
+ <translation>Received from</translation>
+ </message>
+ <message>
<source>Sent to</source>
<translation>Enviar a</translation>
</message>
@@ -1607,6 +3174,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Minado </translation>
</message>
<message>
+ <source>watch-only</source>
+ <translation>watch-only</translation>
+ </message>
+ <message>
<source>(n/a)</source>
<translation>(n/a)</translation>
</message>
@@ -1615,6 +3186,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>(sin etiqueta)</translation>
</message>
<message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Transaction status. Hover over this field to show number of confirmations.</translation>
+ </message>
+ <message>
<source>Date and time that the transaction was received.</source>
<translation>Fecha y hora en que la transacción fue recibida </translation>
</message>
@@ -1623,6 +3198,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Escriba una transacción</translation>
</message>
<message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Whether or not a watch-only address is involved in this transaction.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>User-defined intent/purpose of the transaction.</translation>
+ </message>
+ <message>
<source>Amount removed from or added to balance.</source>
<translation>Cantidad removida del saldo o agregada </translation>
</message>
@@ -1654,6 +3237,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Este año</translation>
</message>
<message>
+ <source>Range...</source>
+ <translation>Range...</translation>
+ </message>
+ <message>
<source>Received with</source>
<translation>Recibido con</translation>
</message>
@@ -1674,10 +3261,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Otro</translation>
</message>
<message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Enter address, transaction id, or label to search</translation>
+ </message>
+ <message>
<source>Min amount</source>
<translation>Monto minimo </translation>
</message>
<message>
+ <source>Abandon transaction</source>
+ <translation>Abandon transaction</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Increase transaction fee</translation>
+ </message>
+ <message>
<source>Copy address</source>
<translation>Copiar dirección </translation>
</message>
@@ -1694,10 +3293,22 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Copiar identificación de la transacción. </translation>
</message>
<message>
+ <source>Copy raw transaction</source>
+ <translation>Copy raw transaction</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>Copy full transaction details</translation>
+ </message>
+ <message>
<source>Edit label</source>
<translation>Editar capa </translation>
</message>
<message>
+ <source>Show transaction details</source>
+ <translation>Show transaction details</translation>
+ </message>
+ <message>
<source>Export Transaction History</source>
<translation>Exportar el historial de transacción</translation>
</message>
@@ -1710,6 +3321,10 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Confirmado </translation>
</message>
<message>
+ <source>Watch-only</source>
+ <translation>Watch-only</translation>
+ </message>
+ <message>
<source>Date</source>
<translation>Fecha</translation>
</message>
@@ -1746,25 +3361,57 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>el historial de transaciones ha sido guardado exitosamente en %1</translation>
</message>
<message>
+ <source>Range:</source>
+ <translation>Range:</translation>
+ </message>
+ <message>
<source>to</source>
<translation>Para</translation>
</message>
</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>Unit to show amounts in. Click to select another unit.</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
<translation>Cerrar cartera</translation>
</message>
- </context>
+ <message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Are you sure you wish to close the wallet &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>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>Close all wallets</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Are you sure you wish to close all wallets?</translation>
+ </message>
+</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No se há cargado la cartera.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Crear una nueva cartera</translation>
</message>
</context>
<context>
@@ -1774,6 +3421,54 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Enviar monedas</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>Fee bump error</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Increasing transaction fee failed</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Do you want to increase the fee?</translation>
+ </message>
+ <message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Do you want to draft a transaction with fee increase?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>Current fee:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>Increase:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>New fee:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>Confirm fee bump</translation>
+ </message>
+ <message>
+ <source>Can't draft transaction.</source>
+ <translation>Can't draft transaction.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT copied</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>Can't sign transaction.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>Could not commit transaction</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>cartera predeterminada</translation>
</message>
@@ -1789,17 +3484,205 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Exportar la información en la pestaña actual a un archivo</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Unable to decode PSBT from clipboard (invalid base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Load Transaction Data</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Partially Signed Transaction (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PSBT file must be smaller than 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Unable to decode PSBT</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Backup Wallet</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Wallet Data (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Backup Failed</translation>
+ </message>
+ <message>
<source>There was an error trying to save the wallet data to %1.</source>
<translation>Ocurrio un error tratando de guardar la información de la cartera %1</translation>
</message>
<message>
+ <source>Backup Successful</source>
+ <translation>Backup Successful</translation>
+ </message>
+ <message>
<source>The wallet data was successfully saved to %1.</source>
<translation>La información de la cartera fué guardada exitosamente a %1</translation>
</message>
- </context>
+ <message>
+ <source>Cancel</source>
+ <translation>Cancel</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Distributed under the MIT software license, see the accompanying file %s or %s</translation>
+ </message>
+ <message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>Prune configured below the minimum of %d MiB. Please use a higher number.</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>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation>
+ </message>
+ <message>
+ <source>Pruning blockstore...</source>
+ <translation>Pruning blockstore...</translation>
+ </message>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>Unable to start HTTP server. See debug log for details.</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <translation>The %s developers</translation>
+ </message>
+ <message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Cannot provide specific connections and have addrman find outgoing connections at the same.</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>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</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>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Please contribute if you find %s useful. Visit %s for further information about the software.</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>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</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>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>This is the transaction fee you may discard if change is smaller than dust at this level</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</translation>
+ </message>
+ <message>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</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>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
+ </message>
+ <message>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>-maxmempool must be at least %d MB</translation>
+ </message>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>Cannot resolve -%s address: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>Change index out of range</translation>
+ </message>
+ <message>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation>Config setting for %s only applied on %s network when in [%s] section.</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>Corrupted block database detected</translation>
+ </message>
+ <message>
+ <source>Could not find asmap file %s</source>
+ <translation>Could not find asmap file %s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Could not parse asmap file %s</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>Do you want to rebuild the block database now?</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation>Error initializing block database</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation>Error initializing wallet database environment %s!</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Error loading %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Error loading %s: Private keys can only be disabled during creation</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Error loading %s: Wallet corrupted</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Error loading %s: Wallet requires newer version of %s</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>Error loading block database</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>Error opening block database</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>Failed to listen on any port. Use -listen=0 if you want this.</translation>
+ </message>
+ <message>
<source>Failed to rescan the wallet during initialization</source>
<translation>Falló al volver a escanear la cartera durante la inicialización</translation>
</message>
@@ -1808,6 +3691,50 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Importando...</translation>
</message>
<message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>Incorrect or no genesis block found. Wrong datadir for network?</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>Initialization sanity check failed. %s is shutting down.</translation>
+ </message>
+ <message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Invalid P2P permission: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Invalid amount for -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Specified blocks directory "%s" does not exist.</translation>
+ </message>
+ <message>
+ <source>Unknown address type '%s'</source>
+ <translation>Unknown address type '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation>Unknown change type '%s'</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Upgrading txindex database</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>Loading P2P addresses...</translation>
+ </message>
+ <message>
<source>Loading banlist...</source>
<translation>Cargando la lista de anuncios...</translation>
</message>
@@ -1816,30 +3743,184 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>No hay suficientes descriptores de archivos disponibles.</translation>
</message>
<message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>Prune cannot be configured with a negative value.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>Prune mode is incompatible with -txindex.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>Replaying blocks...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>Rewinding blocks...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>The source code is available from %s.</translation>
+ </message>
+ <message>
<source>Transaction fee and change calculation failed</source>
<translation>La tarifa de la transacción y el cálculo del cambio fallaron</translation>
</message>
<message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Unable to bind to %s on this computer. %s is probably already running.</translation>
+ </message>
+ <message>
<source>Unable to generate keys</source>
<translation>Incapaz de generar claves</translation>
</message>
<message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Unsupported logging category %s=%s.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>Upgrading UTXO database</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation>User Agent comment (%s) contains unsafe characters.</translation>
+ </message>
+ <message>
<source>Verifying blocks...</source>
<translation>Verificando bloques...</translation>
</message>
<message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>Wallet needed to be rewritten: restart %s to complete</translation>
+ </message>
+ <message>
+ <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
+ <translation>Error: Listening for incoming connections failed (listen returned error %s)</translation>
+ </message>
+ <message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</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>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>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 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>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</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>This is the maximum transaction fee you pay (in addition to the normal fee) to prioritize partial spend avoidance over regular coin selection.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</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>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</translation>
+ </message>
+ <message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>A fatal internal error occurred, see debug.log for details</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Cannot set -peerblockfilters without -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Disk space is too low!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Error de lectura de la base de datos, apagando.</translation>
</message>
<message>
+ <source>Error upgrading chainstate database</source>
+ <translation>Error upgrading chainstate database</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low for %s</source>
+ <translation>Error: Disk space is low for %s</translation>
+ </message>
+ <message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Error: Keypool ran out, please call keypoolrefill first</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Fee rate (%s) is lower than the minimum fee rate setting (%s)</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Invalid -onion address or hostname: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Invalid -proxy address or hostname: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
+ <translation>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</translation>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation>Invalid netmask specified in -whitelist: '%s'</translation>
+ </message>
+ <message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation>Need to specify a port with -whitebind: '%s'</translation>
+ </message>
+ <message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Prune mode is incompatible with -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>Reducing -maxconnections from %d to %d, because of system limitations.</translation>
+ </message>
+ <message>
+ <source>Section [%s] is not recognized.</source>
+ <translation>Section [%s] is not recognized.</translation>
+ </message>
+ <message>
<source>Signing transaction failed</source>
<translation>La transacción de firma falló</translation>
</message>
<message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Specified -walletdir "%s" does not exist</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Specified -walletdir "%s" is a relative path</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Specified -walletdir "%s" is not a directory</translation>
+ </message>
+ <message>
+ <source>The specified config file %s does not exist
+</source>
+ <translation>The specified config file %s does not exist
+</translation>
+ </message>
+ <message>
<source>The transaction amount is too small to pay the fee</source>
<translation>El monto de la transacción es demasiado pequeño para pagar la tarifa</translation>
</message>
@@ -1856,18 +3937,58 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>La transacción es demasiado grande</translation>
</message>
<message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>Unable to bind to %s on this computer (bind returned error %s)</translation>
+ </message>
+ <message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation>Unable to create the PID file '%s': %s</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation>Incapaz de generar claves iniciales</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Unknown -blockfilterindex value %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Verificando la(s) cartera(s)...</translation>
</message>
<message>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <translation>Warning: unknown new rules activated (versionbit %i)</translation>
+ </message>
+ <message>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
+ </message>
+ <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>Esta es la tarifa de transacción que puede pagar cuando no se dispone de estimaciones de tarifas.</translation>
</message>
<message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation>%s is set very high!</translation>
+ </message>
+ <message>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Error loading wallet %s. Duplicate -wallet filename specified.</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Starting network threads...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>The wallet will avoid paying less than the minimum relay fee.</translation>
+ </message>
+ <message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
<translation>Esta es la tarifa de transacción mínima que se paga en cada transacción.</translation>
</message>
@@ -1880,14 +4001,34 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Los montos de las transacciones no deben ser negativos</translation>
</message>
<message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>Transaction has too long of a mempool chain</translation>
+ </message>
+ <message>
<source>Transaction must have at least one recipient</source>
<translation>La transacción debe tener al menos un destinatario</translation>
</message>
<message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation>Unknown network specified in -onlynet: '%s'</translation>
+ </message>
+ <message>
<source>Insufficient funds</source>
<translation>Fondos insuficientes</translation>
</message>
<message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Warning: Private keys detected in wallet {%s} with disabled private keys</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Cannot write to data directory '%s'; check permissions.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Cargando indice de bloques... </translation>
</message>
@@ -1896,6 +4037,14 @@ Solicitar pagos (genera códigos QR y bitcoin: URI)
<translation>Cargando billetera...</translation>
</message>
<message>
+ <source>Cannot downgrade wallet</source>
+ <translation>Cannot downgrade wallet</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>Rescanning...</translation>
+ </message>
+ <message>
<source>Done loading</source>
<translation>Carga completa</translation>
</message>
diff --git a/src/qt/locale/bitcoin_es_VE.ts b/src/qt/locale/bitcoin_es_VE.ts
index 2dd3247a5f..a216f0f8e0 100644
--- a/src/qt/locale/bitcoin_es_VE.ts
+++ b/src/qt/locale/bitcoin_es_VE.ts
@@ -132,6 +132,10 @@
<translation>Repita la nueva contraseña</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Mostrar la frase de contraseña</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Cifrar monedero</translation>
</message>
@@ -172,6 +176,14 @@
<translation>Monedero cifrado</translation>
</message>
<message>
+ <source>Wallet to be encrypted</source>
+ <translation>Billetera a ser cifrada</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Su billetera está ahora cifrada</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>IMPORTANTE: Algunas copias de seguridad que hayas hecho de tu archivo de billetera deberían ser reemplazadas con la billetera encriptada generada recientemente. Por razones de seguridad, las copias de seguridad previas del archivo de billetera sin cifrar serán inútiles tan pronto uses la nueva billetera encriptada.</translation>
</message>
@@ -274,6 +286,18 @@
<translation>Abrir URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Crear Billetera...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Crear una nueva billetera</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Actividad de red deshabilitada.</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Reindexando bloques en disco...</translation>
</message>
@@ -386,6 +410,10 @@
<translation>Cerrar monedero</translation>
</message>
<message>
+ <source>default wallet</source>
+ <translation>billetera por defecto</translation>
+ </message>
+ <message>
<source>No wallets available</source>
<translation>Monederos no disponibles</translation>
</message>
@@ -695,6 +723,10 @@
</context>
<context>
<name>OpenWalletActivity</name>
+ <message>
+ <source>default wallet</source>
+ <translation>billetera por defecto</translation>
+ </message>
</context>
<context>
<name>OptionsDialog</name>
@@ -867,6 +899,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -961,10 +996,6 @@
<translation>Cadena de bloques</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Número actual de bloques</translation>
- </message>
- <message>
<source>Last block time</source>
<translation>Hora del último bloque</translation>
</message>
@@ -1051,12 +1082,20 @@
<source>Copy amount</source>
<translation>Copiar cantidad</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>No se pudo desbloquear la billetera.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Código QR</translation>
+ <source>Amount:</source>
+ <translation>Cuantía:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mensaje:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1070,23 +1109,7 @@
<source>&amp;Save Image...</source>
<translation>Guardar Imagen...</translation>
</message>
- <message>
- <source>Address</source>
- <translation>Dirección</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantidad</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiqueta</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Monedero</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1457,14 +1480,22 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Crear una nueva billetera</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
<source>Send Coins</source>
<translation>Enviar monedas</translation>
</message>
- </context>
+ <message>
+ <source>default wallet</source>
+ <translation>billetera por defecto</translation>
+ </message>
+</context>
<context>
<name>WalletView</name>
<message>
@@ -1476,6 +1507,14 @@
<translation>Exportar a un archivo los datos de esta pestaña</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Billetera de Respaldo</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation>Copia de seguridad fallida</translation>
</message>
@@ -1491,7 +1530,11 @@
<source>The wallet data was successfully saved to %1.</source>
<translation>Los datos de la billetera fueron guardados exitosamente al %1</translation>
</message>
- </context>
+ <message>
+ <source>Cancel</source>
+ <translation>Cancelar</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
<message>
diff --git a/src/qt/locale/bitcoin_et.ts b/src/qt/locale/bitcoin_et.ts
index 025527b680..fc47aec50d 100644
--- a/src/qt/locale/bitcoin_et.ts
+++ b/src/qt/locale/bitcoin_et.ts
@@ -507,11 +507,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Rahakott on &lt;b&gt;krüpteeritud&lt;/b&gt; ning hetkel &lt;b&gt;suletud&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Ilmnes kriitiline tõrge. Bitcoin suletakse turvakaalutluste tõttu.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -889,6 +885,17 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialoog</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>või</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1035,10 +1042,6 @@
<translation>Blokiahel</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Plokkide hetkearv</translation>
- </message>
- <message>
<source>Memory usage</source>
<translation>Mälu kasutus</translation>
</message>
@@ -1115,14 +1118,6 @@
<translation>Väljuv</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Jah</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ei</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Teadmata</translation>
</message>
@@ -1165,44 +1160,40 @@
<source>Copy amount</source>
<translation>Kopeeri kogus</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>QR Code</source>
- <translation>QR Kood</translation>
- </message>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Kopeeri Aadress</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>Rahakoti lahtilukustamine ebaõnnestus.</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Salvesta Pilt...</translation>
+ <source>Amount:</source>
+ <translation>Kogus</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Makse Informatsioon</translation>
+ <source>Label:</source>
+ <translation>Märgis:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Aadress</translation>
+ <source>Message:</source>
+ <translation>Sõnum:</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Kogus</translation>
+ <source>Wallet:</source>
+ <translation>Rahakott:</translation>
</message>
<message>
- <source>Label</source>
- <translation>Silt</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Kopeeri Aadress</translation>
</message>
<message>
- <source>Message</source>
- <translation>Sõnum</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Salvesta Pilt...</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Rahakott</translation>
+ <source>Payment information</source>
+ <translation>Makse Informatsioon</translation>
</message>
</context>
<context>
@@ -1903,7 +1894,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Loo uus rahakott</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -1922,6 +1917,10 @@
<translation>Ekspordi kuvatava vahelehe sisu faili</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Viga</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Varunda Rahakott</translation>
</message>
diff --git a/src/qt/locale/bitcoin_eu.ts b/src/qt/locale/bitcoin_eu.ts
index 2881754ac9..3d717a5686 100644
--- a/src/qt/locale/bitcoin_eu.ts
+++ b/src/qt/locale/bitcoin_eu.ts
@@ -70,10 +70,6 @@
<translation>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.</source>
- <translation>Hauek dira ordainketak jasotzeko zure Bitcoin helbideak. Jaso taulako 'Jasotzeko helbide berri bat sortu' botoia erabili helbide berri bat sortzeko.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Helbidea kopiatu</translation>
</message>
@@ -805,6 +801,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -853,28 +852,28 @@
<source>Copy label</source>
<translation>Etiketa kopiatu</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Ezin da diruzorroa desblokeatu.</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Helbidea kopiatu</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Helbidea</translation>
+ <source>Amount:</source>
+ <translation>Kopurua:</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Kopurua</translation>
+ <source>Message:</source>
+ <translation>Mezua:</translation>
</message>
<message>
- <source>Label</source>
- <translation>Izendapen</translation>
+ <source>Wallet:</source>
+ <translation>Diruzorroa:</translation>
</message>
<message>
- <source>Message</source>
- <translation>Mezua</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Helbidea kopiatu</translation>
</message>
</context>
<context>
@@ -1219,7 +1218,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Diruzorro berri bat sortu</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -1241,6 +1244,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Uneko fitxategian datuak esportatu</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Akatsa</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_fa.ts b/src/qt/locale/bitcoin_fa.ts
index 33833baed4..95d987015d 100644
--- a/src/qt/locale/bitcoin_fa.ts
+++ b/src/qt/locale/bitcoin_fa.ts
@@ -7,7 +7,7 @@
</message>
<message>
<source>Create a new address</source>
- <translation>ساخت یک آدرس جدید</translation>
+ <translation>ایجاد یک آدرس جدید</translation>
</message>
<message>
<source>&amp;New</source>
@@ -70,10 +70,6 @@
<translation>اینها آدرس‌های شما برای ارسال وجوه هستند. همیشه قبل از ارسال، مقدار و آدرس گیرنده را بررسی کنید.</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.</source>
- <translation>اینها آدرس بیت کوین های دریافتی شما می باشدند. در تب دریافت از دکمه 'ایحاد آدرس جدید' برای ساخت آدرس جدید استفاده نمائید.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>کپی آدرس</translation>
</message>
@@ -519,6 +515,14 @@
<translation>کیف پول را ببندید</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>همه‌ی کیف پول‌ها را ببند...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>همه‌ی کیف پول‌ها را ببند</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>کیف پول پیش‌فرض</translation>
</message>
@@ -627,10 +631,10 @@
<translation>wallet رمزگذاری شد و در حال حاضر قفل است</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>خطای بحرانی رخ داده است. بیتکوین دیگر به صورت ایمن قادر به ادامه دادن نمی‌باشد و خارج خواهد شد.</translation>
+ <source>Original message:</source>
+ <translation>پیام اصلی:</translation>
</message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -960,6 +964,10 @@
<translation>کیف پول هم در همین دایرکتوری ذخیره می‌شود.</translation>
</message>
<message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>خطا: نمی‌توان پوشه‌ای برای داده‌ها در «%1» ایجاد کرد.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>خطا</translation>
</message>
@@ -1010,6 +1018,10 @@
<source>Hide</source>
<translation>پنهان کردن</translation>
</message>
+ <message>
+ <source>Esc</source>
+ <translation>خروج</translation>
+ </message>
</context>
<context>
<name>OpenURIDialog</name>
@@ -1021,6 +1033,10 @@
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation>بازکردن کیف پول به مشکل خورده است</translation>
+ </message>
+ <message>
<source>Open wallet warning</source>
<translation>هشدار باز کردن کیف پول</translation>
</message>
@@ -1085,6 +1101,10 @@
<translation>حرفه‌ای</translation>
</message>
<message>
+ <source>Enable coin &amp;control features</source>
+ <translation>فعال کردن قابلیت سکه و کنترل</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>باز کردن خودکار درگاه شبکهٔ بیت‌کوین روی روترها. تنها زمانی کار می‌کند که روتر از پروتکل UPnP پشتیبانی کند و این پروتکل فعال باشد.</translation>
</message>
@@ -1125,10 +1145,6 @@
<translation>شبکه Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>اتصال به شبکه بیت کوین با استفاده از پراکسی SOCKS5 برای استفاده از سرویس مخفی تور</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>پنجره</translation>
</message>
@@ -1289,6 +1305,53 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>تگفتگو</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>کپی کردن</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>ذخیره...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>بستن</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>مشکل نامشخصی در پردازش عملیات رخ داده.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>ذخیره اطلاعات عملیات</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>میزان کل</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>یا</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>عملیات هنوز به امضا(ها) نیاز دارد.</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(اما این کیف‌‌پول نمی‌تواند عملیات‌ها را امضا کند.)</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>وضعیت عملیات نامشخص است.</translation>
+ </message>
+</context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1519,10 +1582,6 @@
<translation>زنجیره مجموعه تراکنش ها</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>تعداد زنجیره های حاضر</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>استخر حافظه</translation>
</message>
@@ -1567,10 +1626,6 @@
<translation>انتخاب همتا یا جفت برای جزییات اطلاعات</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>لیست سفید شده یا لیست سالم WhiteList</translation>
- </message>
- <message>
<source>Direction</source>
<translation>مسیر</translation>
</message>
@@ -1595,6 +1650,10 @@
<translation>پنجره گره</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>ارتفاع فعلی بلوک</translation>
+ </message>
+ <message>
<source>Decrease font size</source>
<translation>کاهش دادن اندازه فونت</translation>
</message>
@@ -1711,14 +1770,6 @@
<translation>هیچ وقت</translation>
</message>
<message>
- <source>Yes</source>
- <translation>بله</translation>
- </message>
- <message>
- <source>No</source>
- <translation>خیر</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>ناشناس یا نامعلوم</translation>
</message>
@@ -1781,56 +1832,56 @@
<source>Copy amount</source>
<translation>کپی مقدار</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>نمیتوان کیف پول را باز کرد.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>کی یو آر کد Qr Code</translation>
+ <source>Request payment to ...</source>
+ <translation>درخواست واریز به ...</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>کپی کردن &amp;آدرس URL</translation>
+ <source>Address:</source>
+ <translation>آدرس‌ها:</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>کپی آدرس</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;ذخیره کردن تصویر...</translation>
+ <source>Amount:</source>
+ <translation>میزان وجه:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>درخواست پرداخت به %1</translation>
+ <source>Label:</source>
+ <translation>برچسب:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>اطلاعات پرداخت</translation>
+ <source>Message:</source>
+ <translation>پیام:</translation>
</message>
<message>
- <source>URI</source>
- <translation>آدرس URL</translation>
+ <source>Wallet:</source>
+ <translation>کیف پول:</translation>
</message>
<message>
- <source>Address</source>
- <translation>آدرس</translation>
+ <source>Copy &amp;URI</source>
+ <translation>کپی کردن &amp;آدرس URL</translation>
</message>
<message>
- <source>Amount</source>
- <translation>میزان وجه:</translation>
+ <source>Copy &amp;Address</source>
+ <translation>کپی آدرس</translation>
</message>
<message>
- <source>Label</source>
- <translation>برچسب</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;ذخیره کردن تصویر...</translation>
</message>
<message>
- <source>Message</source>
- <translation>پیام</translation>
+ <source>Request payment to %1</source>
+ <translation>درخواست پرداخت به %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>کیف پول</translation>
+ <source>Payment information</source>
+ <translation>اطلاعات پرداخت</translation>
</message>
</context>
<context>
@@ -1971,6 +2022,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>گرد و غبار یا داست:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>تنظیمات مخفی کردن کارمزد عملیات</translation>
+ </message>
+ <message>
<source>Confirmation time target:</source>
<translation>هدف زمانی تایید شدن:</translation>
</message>
@@ -2035,6 +2090,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>آیا برای ارسال کردن یا فرستادن مطمئن هستید؟</translation>
</message>
<message>
+ <source>Save Transaction Data</source>
+ <translation>ذخیره اطلاعات عملیات</translation>
+ </message>
+ <message>
<source>or</source>
<translation>یا</translation>
</message>
@@ -2059,8 +2118,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>تایید کردن ارسال کوین ها</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT کپی شد</translation>
+ <source>Send</source>
+ <translation>ارسال</translation>
</message>
<message>
<source>The recipient address is not valid. Please recheck.</source>
@@ -2285,6 +2344,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>قفل‌گشابی کیف‌پول لغو شد.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>بدون خطا</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>کلید خصوصی برای نشانی وارد شده در دسترس نیست.</translation>
</message>
@@ -2331,6 +2394,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>باز تا %1</translation>
</message>
<message>
+ <source>abandoned</source>
+ <translation>رها شده</translation>
+ </message>
+ <message>
<source>%1/unconfirmed</source>
<translation>%1/تأیید نشده</translation>
</message>
@@ -2419,6 +2486,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>حجم کل تراکنش</translation>
</message>
<message>
+ <source>Merchant</source>
+ <translation>بازرگان</translation>
+ </message>
+ <message>
<source>Debug information</source>
<translation>اطلاعات دی باگ Debug</translation>
</message>
@@ -2477,6 +2548,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>تایید نشده</translation>
</message>
<message>
+ <source>Abandoned</source>
+ <translation>رهاشده</translation>
+ </message>
+ <message>
<source>Confirmed (%1 confirmations)</source>
<translation>تأیید شده (%1 تأییدیه)</translation>
</message>
@@ -2697,12 +2772,16 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
<translation>آیا برای بستن کیف پول مطمئن هستید&lt;i&gt; %1 &lt;/i&gt; ؟</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>همه‌ی کیف پول‌ها را ببند</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>کیف‌پولی بارگذاری نشد.</translation>
+ <source>Create a new wallet</source>
+ <translation>ساخت کیف پول جدید</translation>
</message>
</context>
<context>
@@ -2755,6 +2834,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>صدور داده نوار جاری به یک فایل</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>خطا</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>بازیابی یا پشتیبان گیری کیف پول</translation>
</message>
@@ -2846,6 +2929,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>توصیفگرهای فایل به اندازه کافی در دسترس نیست</translation>
</message>
<message>
+ <source>Replaying blocks...</source>
+ <translation>در حال بازبینی بلوک‌ها...</translation>
+ </message>
+ <message>
<source>The source code is available from %s.</source>
<translation>سورس کد موجود است از %s.</translation>
</message>
@@ -2870,6 +2957,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>خواندن از پایگاه داده با خطا مواجه شد,در حال خاموش شدن.</translation>
</message>
<message>
+ <source>Error upgrading chainstate database</source>
+ <translation>خطا در بارگذاری پایگاه داده ها</translation>
+ </message>
+ <message>
<source>Invalid -proxy address or hostname: '%s'</source>
<translation>آدرس پراکسی یا هاست نامعتبر: ' %s'</translation>
</message>
@@ -2906,11 +2997,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>هشدار: قوانین جدید ناشناخته‌ای فعال شده‌اند (نسخه‌بیت %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>تراکنش بیش از حد طولانی از یک زنجیر مهر و موم شده است
-</translation>
- </message>
- <message>
<source>This is the transaction fee you may pay when fee estimates are not available.</source>
<translation>این هزینه تراکنشی است که در صورت عدم وجود هزینه تخمینی، پرداخت می کنید.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fi.ts b/src/qt/locale/bitcoin_fi.ts
index 5af9f5f055..6d5d9c9e2e 100644
--- a/src/qt/locale/bitcoin_fi.ts
+++ b/src/qt/locale/bitcoin_fi.ts
@@ -70,8 +70,10 @@
<translation>Nämä ovat Bitcoin-osoitteesi maksujen lähettämistä varten. Tarkista aina määrä ja vastaanotto-osoite ennen kolikoiden lähettämistä.</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.</source>
- <translation>Nämä ovat sinun Bitcoin osoitteesi maksujen vastaanottamista varten. Käytä 'Luo uusi vastaanotto-osoite' painiketta vastaantto tabissä luodaksesi uuden osoitteen.</translation>
+ <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>Nämä ovat Bitcoin-osoitteesi maksujen vastaanottoa varten. Käytä painiketta "Luo uusi vastaanotto-osoite" vastaanottovälilehdessä luodaksesi uusia osoitteita.
+Allekirjoitus on mahdollista vain 'legacy'-tyyppisillä osoitteilla.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>Rahansiirtohistoria on ajan tasalla</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Lataa PSBT (osittain allekirjoitettu bitcoin-siirto) tiedostosta...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Lataa osittain allekirjoitettu bitcoin-siirtotapahtuma</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Lataa PSBT (osittain allekirjoitettu bitcoin-siirto) leikepöydältä...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Lataa osittain allekirjoitettu bitcoin-siirtotapahtuma leikepöydältä</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Solmu ikkuna</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Sulje lompakko</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Sulje kaikki lompakot...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Sulje kaikki lompakot</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Näytä %1 ohjeet saadaksesi listan mahdollisista Bitcoinin komentorivivalinnoista</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Naamioi arvot</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Naamioi arvot Yhteenveto-välilehdessä</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>oletuslompakko</translation>
</message>
@@ -630,8 +664,12 @@
<translation>Lompakko on &lt;b&gt;salattu&lt;/b&gt; ja tällä hetkellä &lt;b&gt;lukittuna&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Peruuttamaton virhe on tapahtunut. Bitcoin ei voi enää jatkaa turvallisesti ja sammutetaan.</translation>
+ <source>Original message:</source>
+ <translation>Alkuperäinen viesti:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Peruuttamaton virhe on tapahtunut. %1 ei voi enää jatkaa turvallisesti ja sammutetaan.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Luo tyhjä lompakko</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Käytä kuvaajia sciptPubKeyn hallinnointiin</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Kuvaajalompakko</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Luo</translation>
</message>
@@ -1139,10 +1185,6 @@
<translation>Ilmoittaa, mikäli oletetettua SOCKS5-välityspalvelinta käytetään vertaisten tavoittamiseen tämän verkkotyypin kautta.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Käytä SOCKS&amp;5-välityspalvelinta tavoittamaan Tor-verkon piilotetut palvelut:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Piilota kuvake järjestelmäpalkista.</translation>
</message>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Yhdistä Bitcoin-verkkoon erillisen SOCKS5-välityspalvelimen kautta piilotettuja Tor-palveluja varten.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Ikkuna</translation>
</message>
@@ -1319,6 +1357,14 @@
<translation>Näytetäänkö kolikkokontrollin ominaisuuksia vai ei</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Yhdistä Bitcoin-verkkoon erillisen SOCKS5-välityspalvelimen kautta Torin onion-palveluja varten.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Käytä erillistä SOCKS&amp;5-välityspalvelinta tavoittaaksesi vertaisia Torin onion-palvelujen kautta:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;Kolmannen osapuolen rahansiirto URL:t</translation>
</message>
@@ -1453,6 +1499,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Nykyinen tase seurattavassa osoitetteissa</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Yksityisyysmoodi aktivoitu Yhteenveto-välilehdestä. Paljastaaksesi arvot raksi pois Asetukset-&gt;Naamioi arvot.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialogi</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Allekirjoita Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Lähetä Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Kopioi leikepöydälle</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Tallenna...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Sulje</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Siirtoa ei voitu ladata: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Siirtoa ei voitu allekirjoittaa: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Syötteitä ei voitu enää allekirjoittaa.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>%1 syötettä allekirjoitettiin, mutta lisää allekirjoituksia tarvitaan.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Siirto allekirjoitettiin onnistuneesti. Siirto on valmis lähetettäväksi.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Siirron käsittelyssä tapahtui tuntematon virhe.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Siirto lähetettiin onnistuneesti! Siirtotunniste: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Siirron lähetys epäonnstui: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT (osittain allekirjoitettu bitcoin-siirto) kopioitiin leikepöydälle.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Tallenna siirtotiedot</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Osittain tallennettu siirto (binääri) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT (osittain tallennettu bitcoin-siirto) tallennettiin levylle.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>*Lähettää %1'n kohteeseen %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Siirtokuluja tai siirron lopullista määrää ei voitu laskea.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Maksaa siirtokulut:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Yhteensä</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>tai</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Siirrossa on %1 allekirjoittamatonta syötettä.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Siirto kaipaa tietoa syötteistä.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Siirto tarvitsee vielä allekirjoituksia.</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Mutta tämä lompakko ei voi allekirjoittaa siirtoja.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Mutta tällä lompakolla ei ole oikeita avaimia.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Siirto on täysin allekirjoitettu ja valmis lähetettäväksi.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Siirron tila on tuntematon.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1619,6 +1792,10 @@
<translation>Virhe: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Virhe alustaessa asetuksia: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 ei vielä sulkeutunut turvallisesti...</translation>
</message>
@@ -1717,10 +1894,6 @@
<translation>Lohkoketju</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Nykyinen Lohkojen määrä</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Muistiallas</translation>
</message>
@@ -1765,10 +1938,6 @@
<translation>Valitse vertainen eriteltyjä tietoja varten.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Sallittu</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Suunta</translation>
</message>
@@ -1805,6 +1974,10 @@
<translation>Solmun näkymä</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Lohkon nykyinen korkeus</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>Avaa %1 -debug-loki tämänhetkisestä data-hakemistosta. Tämä voi viedä muutaman sekunnin suurille lokitiedostoille.</translation>
</message>
@@ -1817,12 +1990,12 @@
<translation>Suurenna fontin kokoa</translation>
</message>
<message>
- <source>Services</source>
- <translation>Palvelut</translation>
+ <source>Permissions</source>
+ <translation>Luvat</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Panna-pisteytys</translation>
+ <source>Services</source>
+ <translation>Palvelut</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2146,6 @@
<translation>Ulosmenevä</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Kyllä</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ei</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Tuntematon</translation>
</message>
@@ -2079,56 +2244,60 @@
<source>Copy amount</source>
<translation>Kopioi määrä</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Lompakkoa ei voitu avata.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Uutta %1-osoitetta ei voitu luoda</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-koodi</translation>
+ <source>Request payment to ...</source>
+ <translation>Pyydä maksua osoitteeseen...</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>Kopioi &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Kopioi &amp;Osoite</translation>
+ <source>Address:</source>
+ <translation>Osoite:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Tallenna kuva</translation>
+ <source>Amount:</source>
+ <translation>Määrä:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Pyydä maksua osoitteeseen %1</translation>
+ <source>Label:</source>
+ <translation>Tunniste:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Maksutiedot</translation>
+ <source>Message:</source>
+ <translation>Viesti:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Lompakko:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Osoite</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Kopioi &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Määrä</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Kopioi &amp;Osoite</translation>
</message>
<message>
- <source>Label</source>
- <translation>Nimike</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Tallenna kuva</translation>
</message>
<message>
- <source>Message</source>
- <translation>Viesti</translation>
+ <source>Request payment to %1</source>
+ <translation>Pyydä maksua osoitteeseen %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Lompakko</translation>
+ <source>Payment information</source>
+ <translation>Maksutiedot</translation>
</message>
</context>
<context>
@@ -2373,8 +2542,20 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Oletko varma, että haluat lähettää?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Ole hyvä ja katso siirtotapahtuma ehdotuksesi. Tämä tuottaa osittain allekirjoitetun bitcoin-siirtotapahtuman (PSBT), jonka voit kopioida ja sitten allekirjoittaa esimerkiksi offline %1 lompakko tai PSBT-yhteensopiva hardware-lompakko.</translation>
+ <source>Create Unsigned</source>
+ <translation>Luo allekirjoittamaton</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Tallenna siirtotiedot</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Osittain tallennettu siirtotapahtuma (binääri) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT tallennettu</translation>
</message>
<message>
<source>or</source>
@@ -2385,6 +2566,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Voit korottaa palkkiota myöhemmin (osoittaa Replace-By-Fee:tä, 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>
+ <translation>Ole hyvä ja tarkista siirtoehdotuksesi. Tämä luo osittain allekirjoitetun Bitcoin-siirron (PBST), jonka voit tallentaa tai kopioida ja sitten allekirjoittaa esim. verkosta irrannaisella %1-lompakolla tai PBST-yhteensopivalla laitteistolompakolla.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Tarkistathan siirtosi.</translation>
</message>
@@ -2413,18 +2598,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Vahvista siirtoehdotus</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Kopioi PSBT leikepöydälle</translation>
- </message>
- <message>
<source>Send</source>
<translation>Lähetä</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT kopioitu</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Katselulompakon saldo:</translation>
</message>
@@ -3202,12 +3379,28 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Lompakon sulkeminen liian pitkäksi aikaa saattaa johtaa tarpeeseen synkronoida koko ketju uudelleen, mikäli karsinta on käytössä.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Sulje kaikki lompakot</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Haluatko varmasti sulkea kaikki lompakot?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Lomakkoa ei ole ladattu.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Lompakkoa ei ladattu.
+Siirry osioon Tiedosto &gt; Avaa lompakko ladataksesi lompakon.
+- TAI -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Luo uusi lompakko</translation>
</message>
</context>
<context>
@@ -3280,6 +3473,30 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Vie auki olevan välilehden tiedot tiedostoon</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Virhe</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>PBST-ää ei voitu tulkita leikepöydältä (kelpaamaton base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Lataa siirtotiedot</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Osittain allekirjoitettu siirto (*.pbst)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PBST-tiedoston tulee olla pienempi kuin 100 mebitavua</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>PSBT-ää ei voitu tulkita</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Varmuuskopioi lompakko</translation>
</message>
@@ -3323,10 +3540,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Karsinta: viime lompakon synkronisointi menee karsitun datan taakse. Sinun tarvitsee ajaa -reindex (lataa koko lohkoketju uudelleen tapauksessa jossa karsiva noodi)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Virhe: Kriittinen sisäinen virhe kohdattiin, katso debug.log lisätietoja varten</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Karsitaan lohkovarastoa...</translation>
</message>
@@ -3339,10 +3552,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>%s kehittäjät</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Vaihtorahaosoitetta ei voida luoda. Sisäisessä varannossa ei ole avaimia, eikä uusia avaimia voida luoda.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Ei voida lukita data-hakemistoa %s. %s on luultavasti jo käynnissä.</translation>
</message>
@@ -3355,6 +3564,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Virhe luettaessa %s! Avaimet luetttiin oikein, mutta rahansiirtotiedot tai osoitekirjan sisältö saattavat olla puutteellisia tai vääriä.</translation>
</message>
<message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation>Useampi onion bind -osoite on tarjottu. Automaattisesti luotua Torin onion-palvelua varten käytetään %s.</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>Tarkistathan että tietokoneesi päivämäärä ja kellonaika ovat oikeassa! Jos kellosi on väärässä, %s ei toimi oikein.</translation>
</message>
@@ -3363,6 +3576,14 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Ole hyvä ja avusta, jos %s on mielestäsi hyödyllinen. Vieraile %s saadaksesi lisää tietoa ohjelmistosta.</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: Lausekkeen valmistelu sqlite-lompakkokaavioversion %s noutamista varten epäonnistui</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Lausekkeen valmistelu sovellustunnisteen %s noutamista varten epäonnistui</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>Lohkotietokanta sisältää lohkon, joka vaikuttaa olevan tulevaisuudesta. Tämä saattaa johtua tietokoneesi virheellisesti asetetuista aika-asetuksista. Rakenna lohkotietokanta uudelleen vain jos olet varma, että tietokoneesi päivämäärä ja aika ovat oikein.</translation>
</message>
@@ -3391,14 +3612,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Varoitus: Olemme ristiriidassa vertaisten kanssa! Sinun tulee päivittää tai toisten solmujen tulee päivitää.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d viimeisestä 100 lohkosta sisälsi odottamattoman versiotiedon</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s vioittunut, korjaaminen epäonnistui</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool on oltava vähintään %d MB</translation>
</message>
@@ -3475,6 +3688,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Lompakkoa ei voitu tarkastaa alustuksen yhteydessä.</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Tietokannan todennus epäonnistui</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Tuodaan...</translation>
</message>
@@ -3499,6 +3716,30 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Virheellinen määrä -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Lausekkeen suorittaminen tietokannan %s todentamista varten epäonnistui</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: sqlite-lompakkokaavioversion %s nouto epäonnistui</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Sovellustunnisteen %s nouto epäonnistui</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Lausekkeen valmistelu tietokannan %s todentamista varten epäonnistui</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase: Tietokantatodennusvirheen %s luku epäonnistui</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase: Odottamaton sovellustunniste. %u odotettu, %u saatu</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>Määrättyä lohkohakemistoa "%s" ei ole olemassa.</translation>
</message>
@@ -3519,10 +3760,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Ladataan P2P-vertaisten osoitteita...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Virhe: Liian vähän levytilaa!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Ladataan kieltolistaa...</translation>
</message>
@@ -3587,6 +3824,14 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Virhe: Saapuvien yhteyksien kuuntelu epäonnistui (kuuntelu palautti virheen %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s on vioittunut. Yritä käyttää lompakkotyökalua bitcoin-wallet pelastaaksesi sen tai palauttaa varmuuskopio.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Muuta kuin HD-jaettua lompakkoa ei voi päivittää ilman päivitystä tukemaan esijaettua avainvarastoa. Käytä versiota 169900 tai älä kaytä määritettyä versiota.</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>Virheellinen summa -maxtxfee =: '%s' (täytyy olla vähintään %s minrelay-kulu, jotta estetään jumiutuneet siirtotapahtumat)</translation>
</message>
@@ -3595,10 +3840,34 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Siirtomäärä on liian pieni lähetettäväksi kulun vähentämisen jälkeen.</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>Tämä virhe voi tapahtua, jos tämä lompakko ei sammutettu siististi ja ladattiin viimeksi uudempaa Berkeley DB -versiota käyttäneellä ohjelmalla. Tässä tapauksessa käytä sitä ohjelmaa, joka viimeksi latasi tämän lompakon.</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>Tämä on maksimimäärä, jonka maksat siirtokuluina (normaalien kulujen lisäksi) pistääksesi osittaiskulutuksen välttämisen tavallisen kolikonvalinnan edelle.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Siirtoon tarvitaan vaihto-osoite, muttemme voi luoda sitä. Ole hyvä ja kutsu ensin keypoolrefill.</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>Palataksesi karsimattomaan tilaan joudut uudelleenrakentamaan tietokannan -reindex -valinnalla. Tämä lataa koko lohkoketjun uudestaan.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Kriittinen sisäinen virhe kohdattiin, katso debug.log lisätietoja varten</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>-peerblockfiltersiä ei voida asettaa ilman -blockfilterindexiä.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Liian vähän levytilaa!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Virheitä tietokantaa luettaessa, ohjelma pysäytetään.</translation>
</message>
@@ -3611,6 +3880,14 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Virhe: levytila vähissä kohteessa %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Virhe: Avainallas tyhjentyi, ole hyvä ja kutsu keypoolrefill ensin</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Kulutaso (%s) on alempi, kuin minimikulutasoasetus (%s)</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Virheellinen -onion osoite tai isäntänimi: '%s'</translation>
</message>
@@ -3631,6 +3908,10 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>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>Välityspalvelinta ei ole määritetty. Käytä -proxy=&lt;ip&gt; tai -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Karsintatila ei ole yhteensopiva -blockfilterindex valinnan kanssa</translation>
</message>
@@ -3701,10 +3982,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Varoitus: tuntemattomia uusia sääntöjä aktivoitu (versiobitti %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Tyhjennetään kaikki rahansiirrot lompakosta....</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee on asetettu erittäin suureksi! Tämänkokoisia kuluja saatetaan maksaa yhdessä rahansiirrossa.</translation>
</message>
@@ -3717,10 +3994,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Verkon versiokenttä (%i) ylittää sallitun pituuden (%i). Vähennä uacomments:in arvoa tai kokoa.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Varoitus: Lompakkotiedosto on vioittunut, tiedot on korjattu. Alkuperäinen %s talletettu nimellä %s kohteeseen %s; mikäli taseesi tai siirtotapahtumat ovat virheellisiä, on suositeltavaa palauttaa lompakko varmuuskopioista.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s on asetettu todella korkeaksi!</translation>
</message>
@@ -3765,10 +4038,6 @@ Huom: Koska siirtomaksu lasketaan tavujen mukaan, niin määrittelemällä 500 t
<translation>Lompakon saldo ei riitä</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Muuta kuin HD-jaettua lompakkoa ei voi päivittää ilman päivitystä tukemaan esijaettua avainvarastoa. Käytä -upgradewallet = 169900 tai -upgradewallet ilman määritettyä versiota.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Siirtomaksun arviointi epäonnistui. Odota muutama lohko tai käytä -fallbackfee -valintaa..</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fil.ts b/src/qt/locale/bitcoin_fil.ts
index f7b8000439..1051db437b 100644
--- a/src/qt/locale/bitcoin_fil.ts
+++ b/src/qt/locale/bitcoin_fil.ts
@@ -132,6 +132,10 @@
<translation>Ulitin ang bagong passphrase</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Ipakita ang Passphrase</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>I-encrypt ang walet.</translation>
</message>
@@ -172,6 +176,30 @@
<translation>Naka-encrypt ang walet.</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>Ipasok ang bagong passphrase para sa wallet. (1)Mangyaring gumamit ng isang passphrase na(2) sampu o higit pang mga random na characte‭r(2), o (3)walo o higit pang mga salita(3).</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Ipasok ang lumang passphrase at 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>Tandaan na ang pag-encrypt ng iyong pitaka ay hindi maaaring ganap na maprotektahan ang iyong mga bitcoin mula sa pagnanakaw ng malware na nahahawa sa iyong computer.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Ang naka-encrypt na wallet</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Malapit na ma-encrypt ang iyong pitaka.</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Ang iyong wallet ay naka-encrypt na ngayon.</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>MAHALAGA: Anumang nakaraang mga backup na ginawa mo sa iyong walet file ay dapat mapalitan ng bagong-buong, naka-encrypt na walet file. Para sa mga kadahilanang pangseguridad, ang mga nakaraang pag-backup ng hindi naka-encrypt na walet file ay mapagwawalang-silbi sa sandaling simulan mong gamitin ang bagong naka-encrypt na walet.</translation>
</message>
@@ -294,6 +322,14 @@
<translation>Buksan ang URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Gumawa ng Pitaka</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Gumawa ng Bagong Pitaka</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>Walet:</translation>
</message>
@@ -434,6 +470,10 @@
<translation>Napapanahon</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Bintana ng Node</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>Mga address para sa pagpapadala</translation>
</message>
@@ -565,11 +605,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Walet ay na-encrypt at kasalukuyang naka-lock.</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>May nangyaring malubhang kamalian. Hindi na kayang magpatuloy ng ligtas ang Bitcoin at ito ay hihinto na.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -723,10 +759,38 @@
</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Nabigo ang Pag likha ng Pitaka</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Gumawa ng Babala ng Pitaka</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Gumawa ng Pitaka</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Pangalan ng Pitaka</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>Huwag paganahin ang Privbadong susi</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>Gumawa ng Blankong Pitaka</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Gumawa</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -934,6 +998,10 @@
<translation>Itago</translation>
</message>
<message>
+ <source>Esc</source>
+ <translation>Esc</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>Hindi alam. S-in-i-sync ang mga Header (%1, %2%)...</translation>
</message>
@@ -948,6 +1016,14 @@
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation>Nabigo ang bukas na pitaka</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation>Buksan ang babala sa pitaka</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>walet na default</translation>
</message>
@@ -991,10 +1067,6 @@
<translation>Pinapakita kung ang ibinibigay na default SOCKS5 proxy ay ginagamit upang maabot ang mga peers sa pamamagitan nitong uri ng network.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Gumamit ng hiwalay na SOCKS&amp;5 proxy upang maabot ang mga peers sa pamamagitan ng mga tagong serbisyo ng Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Itago ang icon mula sa trey ng sistema.</translation>
</message>
@@ -1123,10 +1195,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Kumunekta sa Bitcoin network sa pamamagitan ng hiwalay na SOCKS5 proxy para sa mga tagong serbisyo ng Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>Window</translation>
</message>
@@ -1301,7 +1369,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>Kasalukuyang kabuuan ng balanse sa mga watch-only address</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Kabuuang Halaga</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1482,6 +1561,10 @@
<translation>Kamalian sa pag-e-encode ng URI sa QR Code.</translation>
</message>
<message>
+ <source>QR code support not available.</source>
+ <translation>Hindi magagamit ang suporta ng QR code.</translation>
+ </message>
+ <message>
<source>Save QR Code</source>
<translation>I-save ang QR Code</translation>
</message>
@@ -1549,10 +1632,6 @@
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Kasalukuyang dami ng blocks</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1597,10 +1676,6 @@
<translation>Pumili ng peer upang tingnan ang detalyadong impormasyon.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direksyon</translation>
</message>
@@ -1621,10 +1696,23 @@
<translation>Mga block na na-sync</translation>
</message>
<message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation>Ginamit ang na-map na Autonomous System para sa pag-iba-iba ng pagpipilian ng kapwa.</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation>Mapa sa AS
+</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation>Ahente ng User</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Bintana ng Node</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>Buksan ang %1 debug log file mula sa kasalukuyang directoryo ng datos. Maaari itong tumagal ng ilang segundo para sa mga malalaking log file.</translation>
</message>
@@ -1641,10 +1729,6 @@
<translation>Mga serbisyo</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban Score</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Oras ng Koneksyon</translation>
</message>
@@ -1793,14 +1877,6 @@
<translation>Papalabas</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Oo</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Hindi</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Hindi alam</translation>
</message>
@@ -1836,6 +1912,18 @@
<translation>Opsyonal na halaga upang humiling. Iwanan itong walang laman o zero upang hindi humiling ng tiyak na halaga.</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>Isang opsyonal na label upang maiugnay sa bagong address ng pagtanggap (ginamit mo upang makilala ang isang invoice). Nakalakip din ito sa kahilingan sa pagbabayad.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Isang opsyonal na mensahe na naka-attach sa kahilingan sa pagbabayad at maaaring ipakita sa nagpadala.</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp; Lumikha ng bagong address sa pagtanggap</translation>
+ </message>
+ <message>
<source>Clear all fields of the form.</source>
<translation>Burahin ang laman ng lahat ng patlang ng form.</translation>
</message>
@@ -1887,12 +1975,24 @@
<source>Copy amount</source>
<translation>Kopyahin ang halaga</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Hindi magawang ma-unlock ang walet.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Code</translation>
+ <source>Amount:</source>
+ <translation>Halaga:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mensahe:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Walet:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1914,30 +2014,6 @@
<source>Payment information</source>
<translation>Impormasyon sa pagbabayad</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Address</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Halaga</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mensahe</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Walet</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2085,6 +2161,10 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Dust:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Itago ang mga Setting ng bayad sa Transaksyon</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>Kapag mas kaunti ang dami ng transaksyon kaysa sa puwang sa mga blocks, ang mga minero pati na rin ang mga relaying node ay maaaring magpatupad ng minimum na bayad. Ang pagbabayad lamang ng minimum na bayad na ito ay maayos, ngunit malaman na maaari itong magresulta sa hindi kailanmang nagkukumpirmang transaksyon sa sandaling magkaroon ng higit na pangangailangan para sa mga transaksyon ng bitcoin kaysa sa kayang i-proseso ng network.</translation>
</message>
@@ -2153,10 +2233,18 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>%1 (%2 mga block)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Lumikha ng Unsigned</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 sa %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Nais mo bang i-draft ang transaksyong ito?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<translation>Sigurado ka bang nais mong magpadala?</translation>
</message>
@@ -2185,10 +2273,26 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Kabuuang Halaga</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>Upang suriin ang listahan ng tatanggap i-click ang "Ipakita ang Mga Detalye ..."</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>Kumpirmahin magpadala ng coins</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <translation>Kumpirmahin ang panukala sa transaksyon</translation>
+ </message>
+ <message>
+ <source>Send</source>
+ <translation>Ipadala</translation>
+ </message>
+ <message>
+ <source>Watch-only balance:</source>
+ <translation>Balanse lamang sa panonood:</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Ang address ng tatanggap ay hindi wasto. Mangyaring suriin muli.</translation>
</message>
@@ -2442,6 +2546,10 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Kinansela ang pag-unlock ng walet.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>Walang Kamalian</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>Hindi magagamit ang private key para sa pinasok na address.</translation>
</message>
@@ -2942,12 +3050,12 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Ang pagsasara ng walet nang masyadong matagal ay maaaring magresulta sa pangangailangan ng pag-resync sa buong chain kung pinagana ang pruning.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Walang walet ang na-load.</translation>
+ <source>Create a new wallet</source>
+ <translation>Gumawa ng Bagong Pitaka</translation>
</message>
</context>
<context>
@@ -2985,6 +3093,14 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Kumpirmahin ang fee bump</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>Hindi ma-draft ang transaksyon</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>Kinopya ang PSBT</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Hindi mapirmahan ang transaksyon.</translation>
</message>
@@ -3008,6 +3124,10 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Angkatin ang datos sa kasalukuyang tab sa talaksan</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Kamalian</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup na walet</translation>
</message>
@@ -3051,10 +3171,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Prune: ang huling pag-synchronize ng walet ay lampas sa pruned data. Kailangan mong mag-reindex (i-download muli ang buong blockchain sa kaso ng pruned node)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Kamalian: May naganap na isang nakamamatay na panloob na error, tingnan ang debug.log para sa detalye</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
@@ -3067,10 +3183,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Ang mga %s developers</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Hindi makagawa ng change-address key. Walang mga key sa panloob na keypool at hindi makagawa ng anumang mga key.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Hindi makakuha ng lock sa direktoryo ng data %s. Malamang na tumatakbo ang %s.</translation>
</message>
@@ -3115,14 +3227,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Babala: Mukhang hindi kami ganap na sumasang-ayon sa aming mga peers! Maaaring kailanganin mong mag-upgrade, o ang ibang mga node ay maaaring kailanganing mag-upgrade.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d ng huling 100 na mga block ay may hindi inaasahang bersyon</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s tiwali, nabigo ang pag-salvage</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>ang -maxmempool ay dapat hindi bababa sa %d MB</translation>
</message>
@@ -3397,10 +3501,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Babala: na-activate ang mga hindi kilalang bagong patakaran (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Z-in-a-zap ang lahat ng mga transaksyon mula sa walet...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee ay nakatakda nang napakataas! Ang mga bayad na ganito kalaki ay maaaring bayaran sa isang solong transaksyon.</translation>
</message>
@@ -3413,10 +3513,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Ang kabuuang haba ng string ng bersyon ng network (%i) ay lumampas sa maximum na haba (%i). Bawasan ang bilang o laki ng mga uacomment.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Babala: Ang file ng walet ay tiwali, ang data ay nailigtas! Nai-save ang original na %s bilang %s sa %s; kung ang iyong balanse o mga transaksyon ay hindi tama dapat mong ibalik mula sa backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>Ang %s ay nakatakda ng napakataas!</translation>
</message>
@@ -3461,10 +3557,6 @@ Tandaan: Dahil ang bayad ay kinakalkula sa bawat-byte na batayan, ang bayad ng
<translation>Hindi sapat na pondo</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Hindi ma-upgrade ang non HD split wallet kung hindi mag-u-upgrade upang suportahan ang pre split keypool. Mangyaring gamitin ang -upgradewallet=169900 o -upgradewallet na walang tinukoy na bersyon.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Nabigo ang pagtatantya ng bayad. Hindi pinagana ang Fallbackfee. Maghintay ng ilang mga block o paganahin -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_fr.ts b/src/qt/locale/bitcoin_fr.ts
index e7066131b6..aa30c6a0e7 100644
--- a/src/qt/locale/bitcoin_fr.ts
+++ b/src/qt/locale/bitcoin_fr.ts
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>Copier l’adresse sélectionnée actuellement dans le presse-papiers</translation>
+ <translation>Copier dans le presse-papiers l’adresse sélectionnée actuellement</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -31,7 +31,7 @@
</message>
<message>
<source>Enter address or label to search</source>
- <translation>Saisir une adresse ou une étiquette à rechercher</translation>
+ <translation>Saisissez une adresse ou une étiquette à rechercher</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -67,11 +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>Ce sont vos adresses Bitcoin pour envoyer des paiements. Vérifiez toujours le montant et l’adresse du destinataire avant d’envoyer des pièces.</translation>
+ <translation>Ce sont vos adresses Bitcoin pour envoyer des paiements. Vérifiez toujours le montant et l’adresse du destinataire avant d’envoyer des pièces.</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.</source>
- <translation>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.</translation>
+ <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>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>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -125,7 +127,7 @@
</message>
<message>
<source>Enter passphrase</source>
- <translation>Saisir la phrase de passe</translation>
+ <translation>Saisissez la phrase de passe</translation>
</message>
<message>
<source>New passphrase</source>
@@ -185,7 +187,7 @@
</message>
<message>
<source>Enter the old passphrase and new passphrase for the wallet.</source>
- <translation>Saisir l’ancienne puis la nouvelle phrase de passe du porte-monnaie.</translation>
+ <translation>Saisissez l’ancienne puis la nouvelle phrase de passe du porte-monnaie.</translation>
</message>
<message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
@@ -237,7 +239,7 @@
</message>
<message>
<source>Warning: The Caps Lock key is on!</source>
- <translation>Avertissement : La touche Verr. Maj. est activée !</translation>
+ <translation>Avertissement : La touche Verr. Maj. est activée</translation>
</message>
</context>
<context>
@@ -291,7 +293,7 @@
</message>
<message>
<source>Show information about %1</source>
- <translation>Afficher des informations à propos de %1</translation>
+ <translation>Afficher des renseignements à propos de %1</translation>
</message>
<message>
<source>About &amp;Qt</source>
@@ -299,7 +301,7 @@
</message>
<message>
<source>Show information about Qt</source>
- <translation>Afficher des informations sur Qt</translation>
+ <translation>Afficher des renseignements sur Qt</translation>
</message>
<message>
<source>&amp;Options...</source>
@@ -339,7 +341,7 @@
</message>
<message>
<source>Click to disable network activity.</source>
- <translation>Cliquer pour désactiver l’activité réseau.</translation>
+ <translation>Cliquez pour désactiver l’activité réseau.</translation>
</message>
<message>
<source>Network activity disabled.</source>
@@ -347,7 +349,7 @@
</message>
<message>
<source>Click to enable network activity again.</source>
- <translation>Cliquer pour réactiver l’activité réseau.</translation>
+ <translation>Cliquez pour réactiver l’activité réseau.</translation>
</message>
<message>
<source>Syncing Headers (%1%)...</source>
@@ -363,7 +365,7 @@
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>Envoyer des pièces à une adresse Bitcoin</translation>
+ <translation>Envoyer des pièces à une adresse Bitcoin</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -399,11 +401,11 @@
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Signer les messages avec vos adresses Bitcoin pour prouver que vous les détenez</translation>
+ <translation>Signer les messages avec vos adresses Bitcoin pour prouver que vous les détenez</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Vérifier les messages pour s’assurer qu’ils ont été signés avec les adresses Bitcoin indiquées</translation>
+ <translation>Vérifier les messages pour s’assurer qu’ils ont été signés avec les adresses Bitcoin indiquées</translation>
</message>
<message>
<source>&amp;File</source>
@@ -439,7 +441,7 @@
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
- <translation><numerusform>%n connexion active avec le réseau Bitcoin</numerusform><numerusform>%n connexions actives avec le réseau Bitcoin</numerusform></translation>
+ <translation><numerusform>%n connexion active avec le réseau Bitcoin</numerusform><numerusform>%n connexions actives avec le réseau Bitcoin</numerusform></translation>
</message>
<message>
<source>Indexing blocks on disk...</source>
@@ -475,19 +477,35 @@
</message>
<message>
<source>Information</source>
- <translation>Informations</translation>
+ <translation>Renseignements</translation>
</message>
<message>
<source>Up to date</source>
<translation>À jour</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Charger une TBSP d’un fichier…</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Charger une transaction Bitcoin signée partiellement</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Charger une TBSP du presse-papiers…</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Charger du presse-papiers une transaction Bitcoin signée partiellement</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Fenêtre des nœuds</translation>
</message>
<message>
<source>Open node debugging and diagnostic console</source>
- <translation>Ouvrir une console de débogage de noeuds et de diagnostic</translation>
+ <translation>Ouvrir une console de débogage de nœuds et de diagnostic</translation>
</message>
<message>
<source>&amp;Sending addresses</source>
@@ -503,7 +521,7 @@
</message>
<message>
<source>Open Wallet</source>
- <translation>Ouvrir le porte-monnaie</translation>
+ <translation>Ouvrir un porte-monnaie</translation>
</message>
<message>
<source>Open a wallet</source>
@@ -518,10 +536,26 @@
<translation>Fermer le porte-monnaie</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Fermer tous les porte-monnaie…</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>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>Afficher le message d’aide de %1 pour obtenir la liste des options de ligne de commande Bitcoin possibles.</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Dissimuler les montants</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Dissimuler les montants dans l’onglet Vue d’ensemble</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>porte-monnaie par défaut</translation>
</message>
@@ -586,7 +620,7 @@
<message>
<source>Type: %1
</source>
- <translation>Type  : %1
+ <translation>Type  : %1
</translation>
</message>
<message>
@@ -630,8 +664,12 @@
<translation>Le porte-monnaie est &lt;b&gt;chiffré&lt;/b&gt; et actuellement &lt;b&gt;verrouillé&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Une erreur fatale est survenue. Bitcoin ne peut plus continuer en toute sécurité et va s’arrêter.</translation>
+ <source>Original message:</source>
+ <translation>Message original :</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Une erreur fatale est survenue. %1 ne peut plus continuer de façon sûre et va s’arrêter.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Créer un porte-monnaie vide</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Utiliser des descripteurs pour la gestion des scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Porte-monnaie de descripteurs</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Créer</translation>
</message>
@@ -875,7 +921,7 @@
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>L’adresse saisie « %1 » n’est pas une adresse Bitcoin valide.</translation>
+ <translation>L’adresse saisie « %1 » n’est pas une adresse Bitcoin valide.</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>
@@ -944,7 +990,7 @@
</message>
<message>
<source>As this is the first time the program is launched, you can choose where %1 will store its data.</source>
- <translation>Puisque c’est la première fois que le logiciel est lancé, vous pouvez choisir où %1 stockera ses données.</translation>
+ <translation>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>
@@ -988,7 +1034,7 @@
</message>
<message>
<source>%1 will download and store a copy of the Bitcoin block chain.</source>
- <translation>%1 téléchargera et stockera une copie de la chaîne de blocs Bitcoin.</translation>
+ <translation>%1 téléchargera et stockera une copie de la chaîne de blocs Bitcoin.</translation>
</message>
<message>
<source>The wallet will also be stored in this directory.</source>
@@ -1023,7 +1069,7 @@
</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>Les transactions récentes ne sont peut-être pas encore visibles et par conséquent le solde de votre porte-monnaie est peut-être erroné. Ces informations seront justes quand votre porte-monnaie aura fini de se synchroniser avec le réseau Bitcoin, comme décrit ci-dessous.</translation>
+ <translation>Les transactions récentes ne sont peut-être pas encore visibles et par conséquent le solde de votre porte-monnaie est peut-être erroné. Ces renseignements seront justes quand votre porte-monnaie aura fini de se synchroniser avec le réseau Bitcoin, comme décrit ci-dessous.</translation>
</message>
<message>
<source>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</source>
@@ -1132,17 +1178,13 @@
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>Adresse IP du mandataire (p. ex. IPv4 : 127.0.0.1 / IPv6 : ::1)</translation>
+ <translation>Adresse IP du mandataire (p. ex. 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>Indique si le mandataire SOCKS5 par défaut fourni est utilisé pour atteindre des pairs par ce type de réseau.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Utiliser un mandataire SOCKS&amp;5 séparé pour atteindre les pairs en utilisant les services cachés de Tor.</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Cacher l’icône dans la zone de notification.</translation>
</message>
@@ -1224,7 +1266,7 @@
</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>Ouvrir automatiquement le port du client Bitcoin sur le routeur. Cela ne fonctionne que si votre routeur prend en charge l’UPnP et si la fonction est activée.</translation>
+ <translation>Ouvrir automatiquement le port du client Bitcoin sur le routeur. Cela ne fonctionne que si votre routeur prend en charge l’UPnP et si la fonction est activée.</translation>
</message>
<message>
<source>Map port using &amp;UPnP</source>
@@ -1240,7 +1282,7 @@
</message>
<message>
<source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
- <translation>Se connecter au réseau Bitcoin par un mandataire SOCKS5.</translation>
+ <translation>Se connecter au réseau Bitcoin par un mandataire SOCKS5.</translation>
</message>
<message>
<source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Se connecter au réseau Bitcoin au travers d’un mandataire SOCKS5 séparé pour les services cachés de Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Fenêtre</translation>
</message>
@@ -1319,6 +1357,14 @@
<translation>Afficher ou non les fonctions de contrôle des pièces.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Se connecter au réseau Bitcoin par un mandataire SOCKS5 séparé pour les services onion de Tor.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Utiliser un mandataire SOCKS5 séparé pour atteindre les pairs par les services onion de Tor.</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>URL de transaction &amp;tierces</translation>
</message>
@@ -1348,7 +1394,7 @@
</message>
<message>
<source>Client restart required to activate changes.</source>
- <translation>Le redémarrage du client est exigé pour activer les changements.</translation>
+ <translation>Le client doit être redémarrer pour activer les changements.</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
@@ -1387,7 +1433,7 @@
</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>Les informations affichées peuvent être obsolètes. Votre porte-monnaie se synchronise automatiquement avec le réseau Bitcoin dès qu’une connexion est établie, mais ce processus n’est pas encore achevé.</translation>
+ <translation>Les renseignements affichés peuvent être obsolètes. Votre porte-monnaie se synchronise automatiquement avec le réseau Bitcoin dès qu’une connexion est établie, mais ce processus n’est pas encore achevé.</translation>
</message>
<message>
<source>Watch-only:</source>
@@ -1453,6 +1499,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Solde total actuel dans des adresses juste-regarder</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Le mode privé est activé dans l’onglet Vue d’ensemble. Pour afficher les montants, décocher Paramètres -&gt; Dissimuler les montants.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Fenêtre de dialogue</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Signer la transaction</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Diffuser la transaction</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Copier dans le presse-papiers</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Enregistrer…</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Fermer</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Échec de chargement de la transaction : %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Échec de signature de la transaction : %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Aucune autre entrée n’a pu être signée.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>%1 entrées ont été signées, mais il faut encore d’autres signatures.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>La transaction a été signée avec succès et est prête à être diffusée.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Erreur inconnue lors de traitement de la transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>La transaction a été diffusée avec succès. ID de la transaction : %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Échec de diffusion de la transaction : %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>La TBSP a été copiée dans le presse-papiers.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Enregistrer les données de la transaction</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transaction signée partiellement (fichier binaire) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>La TBSP a été enregistrée sur le disque.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation> * envoie %1 à %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Impossible de calculer les frais de la transaction ou le montant total de la transaction.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Paye des frais de transaction de :</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Montant total</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ou</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>La transaction a %1 entrées non signées.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Il manque des renseignements sur les entrées dans la transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>La transaction a encore besoin d’une ou de signatures.</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Mais ce porte-monnaie ne peut pas signer de transactions.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Mais ce porte-monnaie n’a pas les bonnes clés.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>La transaction est complètement signée et prête à être diffusée.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>L’état de la transaction est inconnu.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1486,11 +1659,11 @@
</message>
<message>
<source>Invalid payment address %1</source>
- <translation>Adresse de paiement invalide %1</translation>
+ <translation>L’adresse de paiement est invalide %1</translation>
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>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>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>
@@ -1532,7 +1705,7 @@
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Saisir une adresse Bitcoin (p. ex. %1)</translation>
+ <translation>Saisissez une adresse Bitcoin (p. ex. %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1619,6 +1792,10 @@
<translation>Erreur : %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Erreur d’initialisation des paramètres : %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 ne s’est pas encore arrêté en toute sécurité…</translation>
</message>
@@ -1670,7 +1847,7 @@
</message>
<message>
<source>&amp;Information</source>
- <translation>&amp;Informations</translation>
+ <translation>&amp;Renseignements</translation>
</message>
<message>
<source>General</source>
@@ -1717,10 +1894,6 @@
<translation>Chaîne de blocs</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Nombre actuel de blocs</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Réserve de mémoire</translation>
</message>
@@ -1762,11 +1935,7 @@
</message>
<message>
<source>Select a peer to view detailed information.</source>
- <translation>Choisir un pair pour voir des informations détaillées.</translation>
- </message>
- <message>
- <source>Whitelisted</source>
- <translation>Dans la liste blanche</translation>
+ <translation>Sélectionnez un pair pour afficher des renseignements détaillés.</translation>
</message>
<message>
<source>Direction</source>
@@ -1805,6 +1974,10 @@
<translation>Fenêtre des nœuds</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Hauteur du bloc courant</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>Ouvrir le fichier journal de débogage de %1 à partir du répertoire de données actuel. Cela peut prendre quelques secondes pour les fichiers journaux de grande taille.</translation>
</message>
@@ -1817,12 +1990,12 @@
<translation>Augmenter la taille de police</translation>
</message>
<message>
- <source>Services</source>
- <translation>Services</translation>
+ <source>Permissions</source>
+ <translation>Autorisations</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Pointage des bannissements</translation>
+ <source>Services</source>
+ <translation>Services</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1878,11 +2051,11 @@
</message>
<message>
<source>In:</source>
- <translation>Entrant :</translation>
+ <translation>Entrant :</translation>
</message>
<message>
<source>Out:</source>
- <translation>Sortant :</translation>
+ <translation>Sortant :</translation>
</message>
<message>
<source>Debug log file</source>
@@ -1954,7 +2127,7 @@
</message>
<message>
<source>(node id: %1)</source>
- <translation>(ID de nœud : %1)</translation>
+ <translation>(ID de nœud : %1)</translation>
</message>
<message>
<source>via %1</source>
@@ -1973,14 +2146,6 @@
<translation>Sortant</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Oui</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Non</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Inconnu</translation>
</message>
@@ -1989,7 +2154,7 @@
<name>ReceiveCoinsDialog</name>
<message>
<source>&amp;Amount:</source>
- <translation>&amp;Montant :</translation>
+ <translation>&amp;Montant :</translation>
</message>
<message>
<source>&amp;Label:</source>
@@ -1997,11 +2162,11 @@
</message>
<message>
<source>&amp;Message:</source>
- <translation>M&amp;essage :</translation>
+ <translation>M&amp;essage :</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>Un message facultatif à joindre à la demande de paiement et qui sera affiché à l’ouverture de celle-ci. Note : Le message ne sera pas envoyé avec le paiement par le réseau Bitcoin.</translation>
+ <translation>Un message facultatif à joindre à la demande de paiement et qui sera affiché à l’ouverture de celle-ci. Note : Le message ne sera pas envoyé avec le paiement par le réseau Bitcoin.</translation>
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
@@ -2013,7 +2178,7 @@
</message>
<message>
<source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source>
- <translation>Un montant facultatif à demander. Ne rien saisir ou un zéro pour ne pas demander de montant précis.</translation>
+ <translation>Un montant facultatif à demander. Ne saisissez rien ou un zéro pour ne pas demander de montant précis.</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>
@@ -2057,11 +2222,11 @@
</message>
<message>
<source>Remove the selected entries from the list</source>
- <translation>Retirer les entrées sélectionnées de la liste</translation>
+ <translation>Supprimer les entrées sélectionnées de la liste</translation>
</message>
<message>
<source>Remove</source>
- <translation>Retirer</translation>
+ <translation>Supprimer</translation>
</message>
<message>
<source>Copy URI</source>
@@ -2079,56 +2244,60 @@
<source>Copy amount</source>
<translation>Copier le montant</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Impossible de déverrouiller le porte-monnaie.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Impossible de générer la nouvelle adresse %1</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Code QR</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Copier l’&amp;URI</translation>
+ <source>Request payment to ...</source>
+ <translation>Demander un paiement à…</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Copier l’&amp;adresse</translation>
+ <source>Address:</source>
+ <translation>Adresse :</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Enregistrer l’image…</translation>
+ <source>Amount:</source>
+ <translation>Montant :</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Demande de paiement à %1</translation>
+ <source>Label:</source>
+ <translation>Étiquette :</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Informations de paiement</translation>
+ <source>Message:</source>
+ <translation>Message :</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Porte-monnaie :</translation>
</message>
<message>
- <source>Address</source>
- <translation>Adresse</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copier l’&amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Montant</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Copier l’&amp;adresse</translation>
</message>
<message>
- <source>Label</source>
- <translation>Étiquette</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Enregistrer l’image…</translation>
</message>
<message>
- <source>Message</source>
- <translation>Message</translation>
+ <source>Request payment to %1</source>
+ <translation>Demande de paiement à %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Porte-monnaie</translation>
+ <source>Payment information</source>
+ <translation>Renseignements de paiement</translation>
</message>
</context>
<context>
@@ -2182,15 +2351,15 @@
</message>
<message>
<source>Insufficient funds!</source>
- <translation>Les fonds sont insuffisants !</translation>
+ <translation>Les fonds sont insuffisants</translation>
</message>
<message>
<source>Quantity:</source>
- <translation>Quantité :</translation>
+ <translation>Quantité :</translation>
</message>
<message>
<source>Bytes:</source>
- <translation>Octets :</translation>
+ <translation>Octets :</translation>
</message>
<message>
<source>Amount:</source>
@@ -2198,15 +2367,15 @@
</message>
<message>
<source>Fee:</source>
- <translation>Frais :</translation>
+ <translation>Frais :</translation>
</message>
<message>
<source>After Fee:</source>
- <translation>Après les frais :</translation>
+ <translation>Après les frais :</translation>
</message>
<message>
<source>Change:</source>
- <translation>Monnaie :</translation>
+ <translation>Monnaie :</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>
@@ -2218,7 +2387,7 @@
</message>
<message>
<source>Transaction Fee:</source>
- <translation>Frais de transaction :</translation>
+ <translation>Frais de la transaction :</translation>
</message>
<message>
<source>Choose...</source>
@@ -2242,7 +2411,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>per kilobyte</source>
- <translation>par kilo-octet</translation>
+ <translation>Par kilo-octet</translation>
</message>
<message>
<source>Hide</source>
@@ -2250,11 +2419,11 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Recommended:</source>
- <translation>Recommandés :</translation>
+ <translation>Recommandés :</translation>
</message>
<message>
<source>Custom:</source>
- <translation>Personnalisés : </translation>
+ <translation>Personnalisés : </translation>
</message>
<message>
<source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
@@ -2274,7 +2443,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Dust:</source>
- <translation>Poussière :</translation>
+ <translation>Poussière :</translation>
</message>
<message>
<source>Hide transaction fee settings</source>
@@ -2290,7 +2459,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Confirmation time target:</source>
- <translation>Estimation du délai de confirmation :</translation>
+ <translation>Estimation du délai de confirmation :</translation>
</message>
<message>
<source>Enable Replace-By-Fee</source>
@@ -2298,7 +2467,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</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>Avec Remplacer-par-des-frais (BIP-125), vous pouvez augmenter les frais de transaction après qu’elle est envoyée. Sans cela, des frais plus élevés peuvent être recommandés pour compenser le risque accru de retard transactionnel.</translation>
+ <translation>Avec Remplacer-par-des-frais (BIP-125), vous pouvez augmenter les frais d’une transaction après qu’elle est envoyée. Sans cela, des frais plus élevés peuvent être recommandés pour compenser le risque accru de retard transactionnel.</translation>
</message>
<message>
<source>Clear &amp;All</source>
@@ -2354,7 +2523,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</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>Crée une transaction Bitcoin partiellement signée (TBPS) à utiliser, par exemple, avec un porte-monnaie %1 hors ligne ou avec un porte-monnaie matériel compatible TBPS.</translation>
+ <translation>Crée une transaction Bitcoin signée partiellement (TBSP) à utiliser, par exemple, avec un porte-monnaie %1 hors ligne ou avec un porte-monnaie matériel compatible TBSP.</translation>
</message>
<message>
<source> from wallet '%1'</source>
@@ -2370,15 +2539,27 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Do you want to draft this transaction?</source>
- <translation>Souhaitez-vous créer une ébauche de cette transaction ?</translation>
+ <translation>Voulez-vous créer une ébauche de cette transaction ?</translation>
</message>
<message>
<source>Are you sure you want to send?</source>
<translation>Voulez-vous vraiment envoyer ?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Veuillez réviser votre proposition de transaction. Une transaction Bitcoin partiellement signée (TBPS) sera produite, que vous pourrez copier puis signer avec, par exemple, un porte-monnaie %1 hors ligne ou avec un porte-monnaie matériel compatible TBPS.</translation>
+ <source>Create Unsigned</source>
+ <translation>Créer une transaction non signée</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Enregistrer les données de la transaction</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transaction signée partiellement (fichier binaire) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>La TBSP a été enregistrée</translation>
</message>
<message>
<source>or</source>
@@ -2389,6 +2570,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Vous pouvez augmenter les frais ultérieurement (signale Remplacer-par-des-frais, 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>
+ <translation>Veuillez réviser votre proposition de transaction. Une transaction Bitcoin partiellement signée (TBSP) sera produite, que vous pourrez enregistrer ou copier puis signer avec, par exemple, un porte-monnaie %1 hors ligne ou avec un porte-monnaie matériel compatible TBSP.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Veuillez vérifier votre transaction.</translation>
</message>
@@ -2417,18 +2602,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Confirmer la proposition de transaction</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copier la TBPS dans le presse-papiers</translation>
- </message>
- <message>
<source>Send</source>
<translation>Envoyer</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>La TBPS a été copiée</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Solde juste-regarder :</translation>
</message>
@@ -2450,11 +2627,11 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
- <translation>Adresse identique trouvée : chaque adresse ne devrait être utilisée qu’une fois.</translation>
+ <translation>Une adresse identique a été trouvée : chaque adresse ne devrait être utilisée qu’une fois.</translation>
</message>
<message>
<source>Transaction creation failed!</source>
- <translation>Échec de création de la transaction !</translation>
+ <translation>Échec de création de la transaction</translation>
</message>
<message>
<source>A fee higher than %1 is considered an absurdly high fee.</source>
@@ -2470,7 +2647,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation>Avertissement : L’adresse Bitcoin est invalide</translation>
+ <translation>Avertissement : L’adresse Bitcoin est invalide</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
@@ -2509,7 +2686,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation>L’adresse Bitcoin à laquelle envoyer le paiement</translation>
+ <translation>L’adresse Bitcoin à laquelle envoyer le paiement</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2525,7 +2702,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Remove this entry</source>
- <translation>Retirer cette entrée</translation>
+ <translation>Supprimer cette entrée</translation>
</message>
<message>
<source>The amount to send in the selected unit</source>
@@ -2533,7 +2710,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</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>Les frais seront déduits du montant envoyé. Le destinataire recevra moins de bitcoins que le montant saisi dans le champ de montant. Si plusieurs destinataires sont sélectionnés, les frais seront partagés également..</translation>
+ <translation>Les frais seront déduits du montant envoyé. Le destinataire recevra moins de bitcoins que le montant saisi dans le champ de montant. Si plusieurs destinataires sont sélectionnés, les frais seront partagés également.</translation>
</message>
<message>
<source>S&amp;ubtract fee from amount</source>
@@ -2557,19 +2734,19 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Saisir une étiquette pour cette adresse afin de l’ajouter à la liste d’adresses utilisées</translation>
+ <translation>Saisissez une étiquette pour cette adresse afin de l’ajouter à la liste d’adresses utilisées</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>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>
+ <translation>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>Payer à :</translation>
+ <translation>Payer à :</translation>
</message>
<message>
<source>Memo:</source>
- <translation>Mémo :</translation>
+ <translation>Mémo :</translation>
</message>
</context>
<context>
@@ -2587,7 +2764,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<name>SignVerifyMessageDialog</name>
<message>
<source>Signatures - Sign / Verify a Message</source>
- <translation>Signatures - Signer / vérifier un message</translation>
+ <translation>Signatures – Signer/vérifier un message</translation>
</message>
<message>
<source>&amp;Sign Message</source>
@@ -2599,7 +2776,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
- <translation>L’adresse Bitcoin avec laquelle signer le message</translation>
+ <translation>L’adresse Bitcoin avec laquelle signer le message</translation>
</message>
<message>
<source>Choose previously used address</source>
@@ -2619,7 +2796,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Enter the message you want to sign here</source>
- <translation>Saisir ici le message que vous désirez signer</translation>
+ <translation>Saisissez ici le message que vous désirez signer</translation>
</message>
<message>
<source>Signature</source>
@@ -2631,7 +2808,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>Signer le message afin de prouver que vous détenez cette adresse Bitcoin</translation>
+ <translation>Signer le message afin de prouver que vous détenez cette adresse Bitcoin</translation>
</message>
<message>
<source>Sign &amp;Message</source>
@@ -2651,11 +2828,11 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</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>Saisir ci-dessous l’adresse du destinataire, le message (s’assurer de copier fidèlement les retours à la ligne, les espaces, les tabulations, etc.) et la signature pour vérifier le message. Faire attention à ne pas déduire davantage de la signature que ce qui est contenu dans le message signé même, pour éviter d’être trompé par une attaque d’homme du milieu. Prendre en compte que cela ne fait que prouver que le signataire reçoit l’adresse et ne peut pas prouver la provenance d’une transaction !</translation>
+ <translation>Saisissez ci-dessous l’adresse du destinataire, le message (assurez-vous de copier fidèlement les retours à la ligne, les espaces, les tabulations, etc.) et la signature pour vérifier le message. Faites attention à ne pas déduire davantage de la signature que ce qui est contenu dans le message signé même, pour éviter d’être trompé par une attaque de l’intercepteur. Notez que cela ne fait que prouver que le signataire reçoit avec l’adresse et ne peut pas prouver la provenance d’une transaction.</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>L’adresse Bitcoin avec laquelle le message a été signé</translation>
+ <translation>L’adresse Bitcoin avec laquelle le message a été signé</translation>
</message>
<message>
<source>The signed message to verify</source>
@@ -2667,7 +2844,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>Vérifier le message pour s’assurer qu’il a été signé avec l’adresse Bitcoin indiquée</translation>
+ <translation>Vérifier le message pour s’assurer qu’il a été signé avec l’adresse Bitcoin indiquée</translation>
</message>
<message>
<source>Verify &amp;Message</source>
@@ -2889,7 +3066,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Debug information</source>
- <translation>Informations de débogage</translation>
+ <translation>Renseignements de débogage</translation>
</message>
<message>
<source>Transaction</source>
@@ -3082,7 +3259,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Enter address, transaction id, or label to search</source>
- <translation>Saisir l’adresse, l’ID de transaction ou l’étiquette à chercher</translation>
+ <translation>Saisissez l’adresse, l’ID de transaction ou l’étiquette à chercher</translation>
</message>
<message>
<source>Min amount</source>
@@ -3193,7 +3370,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<name>UnitDisplayStatusBarControl</name>
<message>
<source>Unit to show amounts in. Click to select another unit.</source>
- <translation>Unité d’affichage des montants. Cliquer pour choisir une autre unité.</translation>
+ <translation>Unité d’affichage des montants. Cliquez pour choisir une autre unité.</translation>
</message>
</context>
<context>
@@ -3210,12 +3387,28 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Fermer le porte-monnaie trop longtemps peut impliquer de devoir resynchroniser la chaîne entière si l’élagage est activé.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Fermer tous les porte-monnaie</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Voulez-vous vraiment fermer tous les porte-monnaie ?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Aucun porte-monnaie n’a été chargé.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Aucun porte-monnaie n’a été chargé.
+Accédez à Fichier &gt; Ouvrir un porte-monnaie pour en charger un.
+– OU –</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Créer un nouveau porte-monnaie</translation>
</message>
</context>
<context>
@@ -3234,23 +3427,23 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Do you want to increase the fee?</source>
- <translation>Souhaitez-vous augmenter les frais ?</translation>
+ <translation>Voulez-vous augmenter les frais ?</translation>
</message>
<message>
<source>Do you want to draft a transaction with fee increase?</source>
- <translation>Souhaitez-vous créer une ébauche de transaction avec une augmentation des frais ?</translation>
+ <translation>Voulez-vous créer une ébauche de transaction avec une augmentation des frais ?</translation>
</message>
<message>
<source>Current fee:</source>
- <translation>Frais actuels :</translation>
+ <translation>Frais actuels :</translation>
</message>
<message>
<source>Increase:</source>
- <translation>Augmentation :</translation>
+ <translation>Augmentation :</translation>
</message>
<message>
<source>New fee:</source>
- <translation>Nouveaux frais :</translation>
+ <translation>Nouveaux frais :</translation>
</message>
<message>
<source>Confirm fee bump</source>
@@ -3288,6 +3481,30 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Exporter les données de l’onglet actuel vers un fichier</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Erreur</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Impossible de décoder la TBSP du presse-papiers (le Base64 est invalide)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Charger les données de la transaction</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Transaction signée partiellement (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>Le fichier de la TBSP doit être inférieur à 100 Mio</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Impossible de décoder la TBSP</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Sauvegarder le porte-monnaie</translation>
</message>
@@ -3320,7 +3537,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<name>bitcoin-core</name>
<message>
<source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
- <translation>Distribué sous la licence MIT d’utilisation d’un logiciel. Consulter le fichier joint %s ou %s</translation>
+ <translation>Distribué sous la licence MIT d’utilisation d’un logiciel, consultez le fichier joint %s ou %s</translation>
</message>
<message>
<source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
@@ -3328,11 +3545,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</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>É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>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Erreur : Une erreur interne fatale s’est produite. Voir debug.log pour plus de détails</translation>
+ <translation>É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>Pruning blockstore...</source>
@@ -3340,15 +3553,11 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Unable to start HTTP server. See debug log for details.</source>
- <translation>Impossible de démarrer le serveur HTTP. Voir le journal de débogage pour plus de détails.</translation>
+ <translation>Impossible de démarrer le serveur HTTP. Consultez le journal de débogage pour plus de précisions.</translation>
</message>
<message>
<source>The %s developers</source>
- <translation>Les développeurs de %s</translation>
- </message>
- <message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Impossible de générer une clé d’adresse de monnaie. Il n’y a pas de clés dans la réserve de clés et il est impossible d’en générer.</translation>
+ <translation>Les développeurs de %s</translation>
</message>
<message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
@@ -3360,19 +3569,35 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <translation>Erreur de lecture de %s ! Toutes les clés ont été lues correctement, mais les données transactionnelles ou les entrées du carnet d’adresses sont peut-être manquantes ou incorrectes.</translation>
+ <translation>Erreur de lecture de %s. Toutes les clés ont été lues correctement, mais les données de la transaction ou les entrées du carnet d’adresses sont peut-être manquantes ou incorrectes.</translation>
+ </message>
+ <message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation>Plus d’une adresse onion de liaison est indiquée. %s sera utilisée pour le service onion de Tor créé automatiquement.</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>Veuillez vérifier que l’heure et la date de votre ordinateur sont justes ! Si votre horloge n’est pas à l’heure, %s ne fonctionnera pas correctement.</translation>
+ <translation>Veuillez vérifier que l’heure et la date de votre ordinateur sont justes. Si votre horloge n’est pas à l’heure, %s ne fonctionnera pas correctement.</translation>
</message>
<message>
<source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
- <translation>Si vous trouvez %s utile, vous pouvez y contribuer. Vous trouverez plus de renseignements au sujet du logiciel sur %s.</translation>
+ <translation>Si vous trouvez %s utile, veuillez y contribuer. Pour de plus de précisions sur le logiciel, rendez-vous sur %s.</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase : échec de préparation de l’instruction pour récupérer la version du schéma de porte-monnaie sqlite : %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>SQLiteDatabase : échec de préparation de l’instruction pour récupérer l’ID de l’application : %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation>SQLiteDatabase : la version %d du schéma de porte-monnaie sqlite est inconnue. Seule la version %d est prise en charge</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>La base de données de blocs contient un bloc qui semble provenir du futur. Cela pourrait être causé par la date et l’heure erronées de votre ordinateur. Ne reconstruisez la base de données de blocs que si vous êtes certain que la date et l’heure de votre ordinateur sont justes.</translation>
+ <translation>La base de données de blocs comprend un bloc qui semble provenir du futur. Cela pourrait être causé par la date et l’heure erronées de votre ordinateur. Ne reconstruisez la base de données de blocs que si vous êtes certain que la date et l’heure de votre ordinateur sont justes.</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>
@@ -3392,19 +3617,11 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
- <translation>Avertissement : Le réseau ne semble pas totalement d’accord ! Certains mineurs semblent éprouver des problèmes.</translation>
+ <translation>Avertissement : Le réseau ne semble pas totalement d’accord. Certains mineurs semblent éprouver des problèmes.</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>Avertissement : Nous ne semblons pas être en accord complet avec nos pairs ! Une mise à niveau pourrait être nécessaire pour vous ou pour d’autres nœuds du réseau.</translation>
- </message>
- <message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d des 100 derniers blocs ont une version inattendue</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrompu, la récupération a échoué</translation>
+ <translation>Avertissement : Nous ne semblons pas être en accord complet avec nos pairs. Une mise à niveau pourrait être nécessaire pour vous ou pour d’autres nœuds du réseau.</translation>
</message>
<message>
<source>-maxmempool must be at least %d MB</source>
@@ -3448,7 +3665,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Error initializing wallet database environment %s!</source>
- <translation>Erreur d’initialisation de l’environnement de la base de données du porte-monnaie %s !</translation>
+ <translation>Erreur d’initialisation de l’environnement de la base de données du porte-monnaie %s.</translation>
</message>
<message>
<source>Error loading %s</source>
@@ -3483,6 +3700,10 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Échec de réanalyse du porte-monnaie lors de l’initialisation</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Échec de vérification de la base de données</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importation…</translation>
</message>
@@ -3496,19 +3717,43 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Invalid P2P permission: '%s'</source>
- <translation>Permission P2P invalide : '%s'</translation>
+ <translation>L’autorisation P2P est invalide : « %s »</translation>
</message>
<message>
<source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
- <translation>Montant invalide pour -%s=&lt;amount&gt; : « %s »</translation>
+ <translation>Le montant est invalide pour -%s=&lt;amount&gt; : « %s »</translation>
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation>Montant invalide pour -discardfee=&lt;amount&gt; : « %s »</translation>
+ <translation>Le montant est invalide pour -discardfee=&lt;amount&gt; : « %s »</translation>
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
- <translation>Montant invalide pour -fallbackfee=&lt;amount&gt; : « %s »</translation>
+ <translation>Le montant est invalide pour -fallbackfee=&lt;amount&gt; : « %s »</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase : échec d’exécution de l’instruction pour vérifier la base de données : %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase : échec de récupération de la version du schéma de porte-monnaie sqlite : %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation>SQLiteDatabase : échec de récupération de l’ID de l’application : %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase : échec de préparation de l’instruction pour vérifier la base de données : %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase : échec de lecture de l’erreur de vérification de la base de données : %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase : l’ID de l’application est inattendu. %u était attendu, %u été retourné</translation>
</message>
<message>
<source>Specified blocks directory "%s" does not exist.</source>
@@ -3516,11 +3761,11 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Unknown address type '%s'</source>
- <translation>Type d’adresse inconnu '%s'</translation>
+ <translation>Le type d’adresse est inconnu « %s »</translation>
</message>
<message>
<source>Unknown change type '%s'</source>
- <translation>Type de monnaie inconnu '%s'</translation>
+ <translation>Le type de monnaie est inconnu « %s »</translation>
</message>
<message>
<source>Upgrading txindex database</source>
@@ -3531,10 +3776,6 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Chargement des adresses P2P…</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Erreur : L’espace disque est trop faible !</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Chargement de la liste d’interdiction…</translation>
</message>
@@ -3584,7 +3825,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>User Agent comment (%s) contains unsafe characters.</source>
- <translation>Le commentaire d’agent utilisateur (%s) contient des caractères dangereux.</translation>
+ <translation>Le commentaire de l’agent utilisateur (%s) comporte des caractères dangereux.</translation>
</message>
<message>
<source>Verifying blocks...</source>
@@ -3596,21 +3837,53 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
- <translation>Erreur : L’écoute des connexions entrantes a échoué (l’écoute a retourné l’erreur %s)</translation>
+ <translation>Erreur : L’écoute des connexions entrantes a échoué (l’écoute a retourné l’erreur %s)</translation>
+ </message>
+ <message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s est corrompu. Essayez l’outil bitcoin-wallet pour le sauver ou restaurez une sauvegarde.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Impossible de mettre à niveau un porte-monnaie divisé non-HD sans mettre à niveau pour prendre en charge la réserve de clés antérieure à la division. Veuillez utiliser la version 169900 ou ne pas indiquer de version.</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>Montant invalide pour -maxtxfee=&lt;amount&gt; : « %s » (doit être au moins les frais minrelay de %s pour prévenir le blocage des transactions)</translation>
+ <translation>Le montant est invalide pour -maxtxfee=&lt;amount&gt; : « %s » (doit être au moins les frais minrelay de %s pour prévenir le blocage des transactions)</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>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>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>
+ </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>Les frais maximaux de transaction que vous payez (en plus des frais habituels) afin de prioriser une dépense non partielle plutôt qu’une sélection normale de pièces.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Une adresse de monnaie est nécessaire à la transaction, mais nous ne pouvons pas la générer. Veuillez d’abord appeler « keypoolrefill ».</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>Vous devez reconstruire la base de données en utilisant -reindex afin de revenir au mode sans élagage. Cela retéléchargera complètement la chaîne de blocs.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Une erreur interne fatale est survenue. Consultez debug.log pour plus de précisions</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Impossible de définir -peerblockfilters sans -blockfilterindex</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>L’espace disque est trop faible !</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Erreur de lecture de la base de données, fermeture en cours.</translation>
</message>
@@ -3623,26 +3896,38 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Erreur : Il reste peu d’espace disque sur %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Erreur : La réserve de clés est épuisée, veuillez d’abord appeler « keypoolrefill »</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Le taux de frais (%s) est inférieur au taux minimal de frais défini (%s)</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
- <translation>Adresse ou nom d’hôte -onion invalide : « %s »</translation>
+ <translation>L’adresse -onion ou le nom d’hôte sont invalides : « %s »</translation>
</message>
<message>
<source>Invalid -proxy address or hostname: '%s'</source>
- <translation>Adresse ou nom d’hôte -proxy invalide : « %s »</translation>
+ <translation>L’adresse -proxy ou le nom d’hôte sont invalides : « %s »</translation>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>Montant invalide pour -paytxfee=&lt;montant&gt; : « %s » (doit être au moins %s)</translation>
+ <translation>Le montant est invalide pour -paytxfee=&lt;montant&gt; : « %s » (doit être au moins %s)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
- <translation>Masque réseau invalide indiqué dans -whitelist : « %s »</translation>
+ <translation>Le masque réseau indiqué dans -whitelist est invalide : « %s »</translation>
</message>
<message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Un port doit être précisé avec -whitebind : « %s »</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>Aucun serveur mandataire n’est indiqué. Utilisez -proxy=&lt;ip&gt; ou -proxy=&lt;ip:port&gt;</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Le mode élagage n’est pas compatible avec -blockfilterindex.</translation>
</message>
@@ -3698,7 +3983,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
- <translation>Impossible de créer le fichier PID '%s' : %s</translation>
+ <translation>Impossible de créer le fichier PID « %s » : %s</translation>
</message>
<message>
<source>Unable to generate initial keys</source>
@@ -3706,7 +3991,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Unknown -blockfilterindex value %s.</source>
- <translation>Valeur -blockfilterindex inconnue %s.</translation>
+ <translation>La valeur -blockfilterindex %s est inconnue.</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
@@ -3717,12 +4002,8 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>Avertissement : De nouvelles règles inconnues ont été activées (bit de version %i).</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Supprimer toutes les transactions du porte-monnaie…</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation>La valeur -maxtxfee est très élevée ! Des frais aussi élevés pourraient être payés en une seule transaction.</translation>
+ <translation>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>This is the transaction fee you may pay when fee estimates are not available.</source>
@@ -3733,12 +4014,8 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
<translation>La taille totale de la chaîne de version de réseau (%i) dépasse la longueur maximale (%i). Réduire le nombre ou la taille des commentaires uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Avertissement : Le fichier du porte-monnaie est corrompu, les données ont été récupérées ! Le fichier %s original a été enregistré en tant que %s dans %s ; si votre solde ou vos transactions sont incorrects, vous devriez restaurer une sauvegarde.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
- <translation>La valeur %s est très élevée !</translation>
+ <translation>La valeur %s est très élevée.</translation>
</message>
<message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
@@ -3774,17 +4051,13 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Unknown network specified in -onlynet: '%s'</source>
- <translation>Réseau inconnu précisé dans -onlynet : « %s »</translation>
+ <translation>Un réseau inconnu est indiqué dans -onlynet : « %s »</translation>
</message>
<message>
<source>Insufficient funds</source>
<translation>Fonds insuffisants</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Impossible de mettre à niveau un porte-monnaie divisé non-HD sans mettre à niveau pour prendre en charge la réserve de clés antérieure à la division. Veuillez utiliser -upgradewallet=169900 ou -upgradewallet sans indiquer de version.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Échec d’estimation des frais. L’option de frais de repli est désactivée. Attendez quelques blocs ou activez -fallbackfee.</translation>
</message>
@@ -3794,7 +4067,7 @@ Note : Les frais étant calculés par octet, des frais de « 100 satoshis par
</message>
<message>
<source>Cannot write to data directory '%s'; check permissions.</source>
- <translation>Impossible d’écrire dans le répertoire de données '%s' ; veuillez vérifier les droits.</translation>
+ <translation>Impossible d’écrire dans le répertoire de données « %s » ; veuillez vérifier les droits.</translation>
</message>
<message>
<source>Loading block index...</source>
diff --git a/src/qt/locale/bitcoin_gl_ES.ts b/src/qt/locale/bitcoin_gl_ES.ts
index 20b9fb1bbd..2438aff7cd 100644
--- a/src/qt/locale/bitcoin_gl_ES.ts
+++ b/src/qt/locale/bitcoin_gl_ES.ts
@@ -70,10 +70,6 @@
<translation>Estes son os teus enderezos de Bitcoin para enviar pagamentos. Asegurate sempre de comprobar a cantidade e maila dirección antes de enviar moedas.</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.</source>
- <translation>Estes son os teus enderezos para recibir pagamentos. Usa o botón 'Crear novo enderezo de recepción' na pestana de recibir para crear un novo enderezo.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>Copiar Enderezo</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>A carteira está &lt;b&gt;encriptada&lt;/b&gt; e actualmente &lt;b&gt;bloqueada&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Produciuse un error fatal. Bitcoin non pode seguir funcionando de maneira segura e sairá.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1139,10 +1131,6 @@
<translation>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Hide the icon from the system tray.</translation>
</message>
@@ -1275,10 +1263,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Window</translation>
</message>
@@ -1453,7 +1437,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>Current total balance in watch-only addresses</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Total Amount</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>or</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1712,6 @@
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Current number of blocks</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1765,10 +1756,6 @@
<translation>Select a peer to view detailed information.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direction</translation>
</message>
@@ -1821,10 +1808,6 @@
<translation>Services</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban Score</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Connection Time</translation>
</message>
@@ -1973,14 +1956,6 @@
<translation>Outbound</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Yes</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Unknown</translation>
</message>
@@ -2079,12 +2054,24 @@
<source>Copy amount</source>
<translation>Copy amount</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Non se puido desbloquear a carteira.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Code</translation>
+ <source>Amount:</source>
+ <translation>Amount:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Message:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Carteira:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2106,30 +2093,6 @@
<source>Payment information</source>
<translation>Payment information</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Address</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Amount</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Message</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Wallet</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2377,10 +2340,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Are you sure you want to send?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
- </message>
- <message>
<source>or</source>
<translation>or</translation>
</message>
@@ -2417,18 +2376,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Confirm transaction proposal</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copy PSBT to clipboard</translation>
- </message>
- <message>
<source>Send</source>
<translation>Send</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copied</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Watch-only balance:</translation>
</message>
@@ -3210,12 +3161,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No wallet has been loaded.</translation>
+ <source>Create a new wallet</source>
+ <translation>Crear unha nova carteira</translation>
</message>
</context>
<context>
@@ -3288,6 +3239,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Export the data in the current tab to a file</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
@@ -3331,10 +3286,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: A fatal internal error occurred, see debug.log for details</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
@@ -3347,10 +3298,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>The %s developers</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
</message>
@@ -3399,14 +3346,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d of last 100 blocks have unexpected version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupt, salvage failed</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool must be at least %d MB</translation>
</message>
@@ -3531,10 +3470,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Loading P2P addresses...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Error: Disk space is too low!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Loading banlist...</translation>
</message>
@@ -3717,10 +3652,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Warning: unknown new rules activated (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zapping all transactions from wallet...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
</message>
@@ -3733,10 +3664,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is set very high!</translation>
</message>
@@ -3781,10 +3708,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Insufficient funds</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_he.ts b/src/qt/locale/bitcoin_he.ts
index 56c37a74dd..bd64fdd179 100644
--- a/src/qt/locale/bitcoin_he.ts
+++ b/src/qt/locale/bitcoin_he.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>לחץ על הכפתור הימני בעכבר כדי לערוך את הכתובת או התווית</translation>
+ <translation>לחיצה על הכפתור הימני בעכבר תערוך את הכתובת או התווית</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>צור כתובת חדשה</translation>
+ <translation>יצירת כתובת חדשה</translation>
</message>
<message>
<source>&amp;New</source>
@@ -15,23 +15,23 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>העתק את הכתובת המסומנת ללוח העריכה</translation>
+ <translation>העתקת את הכתובת המסומנת ללוח</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation>&amp;העתק</translation>
+ <translation>&amp;העתקה</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation>&amp;סגור</translation>
+ <translation>&amp;סגירה</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>מחק את הכתובת המסומנת ברשימה</translation>
+ <translation>מחיקת הכתובת שמסומנת כרגע מהרשימה</translation>
</message>
<message>
<source>Enter address or label to search</source>
- <translation>הכנס כתובת או תווית לחפש</translation>
+ <translation>נא למלא כתובת או תווית לחפש</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -43,15 +43,15 @@
</message>
<message>
<source>&amp;Delete</source>
- <translation>&amp;מחק</translation>
+ <translation>&amp;מחיקה</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>בחר את הכתובת אליה תרצה לשלוח את המטבעות</translation>
+ <translation>נא לבחור את הכתובת לשליחת המטבעות</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>בחר את הכתובת לקבלת המטבעות</translation>
+ <translation>נא לבחור את הכתובת לקבלת המטבעות</translation>
</message>
<message>
<source>C&amp;hoose</source>
@@ -70,12 +70,14 @@
<translation>אלו הן כתובות הביטקוין שלך לשליחת תשלומים. חשוב לבדוק את הסכום ואת הכתובת המקבלת לפני שליחת מטבעות.</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.</source>
- <translation>אלה כתובות הביטקוין שלך לקבלת תשלומים. השתמש בלחצן 'צור כתובת קבלה חדשה' בכרטיסייה קבלה כדי ליצור כתובות חדשות.</translation>
+ <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>אלו כתובת ביטקוין שלך לקבלת תשלומים. ניתן להשתמש בכפתור 'יצירת כתובת קבלה חדשה' בלשונית הקבלה ליצירת כתובות חדשות.
+חתימה אפשרית רק עבור כתובות מסוג 'legacy'.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>&amp;העתק כתובת</translation>
+ <translation>&amp;העתקת כתובת</translation>
</message>
<message>
<source>Copy &amp;Label</source>
@@ -121,11 +123,11 @@
<name>AskPassphraseDialog</name>
<message>
<source>Passphrase Dialog</source>
- <translation>שיח סיסמא</translation>
+ <translation>תיבת דו־שיח סיסמה</translation>
</message>
<message>
<source>Enter passphrase</source>
- <translation>הכנס סיסמה</translation>
+ <translation>יש להזין סיסמה</translation>
</message>
<message>
<source>New passphrase</source>
@@ -137,11 +139,11 @@
</message>
<message>
<source>Show passphrase</source>
- <translation>הצג סיסמה</translation>
+ <translation>הצגת סיסמה</translation>
</message>
<message>
<source>Encrypt wallet</source>
- <translation>הצפן ארנק</translation>
+ <translation>הצפנת ארנק</translation>
</message>
<message>
<source>This operation needs your wallet passphrase to unlock the wallet.</source>
@@ -198,11 +200,11 @@
</message>
<message>
<source>Your wallet is about to be encrypted. </source>
- <translation>הארנק שלך עומד להיות מוצפן/</translation>
+ <translation>הארנק שלך עומד להיות מוצפן.</translation>
</message>
<message>
<source>Your wallet is now encrypted. </source>
- <translation>הארנק שלך מוצפן כעת/</translation>
+ <translation>הארנק שלך מוצפן כעת.</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>
@@ -284,7 +286,7 @@
</message>
<message>
<source>Quit application</source>
- <translation>סגור תוכנה</translation>
+ <translation>יציאה מהיישום</translation>
</message>
<message>
<source>&amp;About %1</source>
@@ -304,7 +306,7 @@
</message>
<message>
<source>&amp;Options...</source>
- <translation>&amp;אפשרויות…</translation>
+ <translation>&amp;אפשרויות...</translation>
</message>
<message>
<source>Modify configuration options for %1</source>
@@ -312,11 +314,11 @@
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>&amp;הצפנת הארנק…</translation>
+ <translation>&amp;הצפנת הארנק...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>&amp;גיבוי הארנק…</translation>
+ <translation>&amp;גיבוי הארנק...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
@@ -324,15 +326,15 @@
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>פתיחת &amp;כתובת משאב…</translation>
+ <translation>פתיחת &amp;כתובת משאב...</translation>
</message>
<message>
<source>Create Wallet...</source>
- <translation>צור ארנק...</translation>
+ <translation>יצירת ארנק...</translation>
</message>
<message>
<source>Create a new wallet</source>
- <translation>צור ארנק חדש</translation>
+ <translation>יצירת ארנק חדש</translation>
</message>
<message>
<source>Wallet:</source>
@@ -372,7 +374,7 @@
</message>
<message>
<source>Change the passphrase used for wallet encryption</source>
- <translation>שנה את הסיסמא המשמשת להצפנת הארנק</translation>
+ <translation>שינוי הסיסמה המשמשת להצפנת הארנק</translation>
</message>
<message>
<source>&amp;Verify message...</source>
@@ -483,6 +485,22 @@
<translation>עדכני</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;העלה PSBT מקובץ...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>העלה עיסקת ביטקוין חתומה חלקית</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>טעינת PSBT מלוח הגזירים...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>טעינת עסקת ביטקוין חתומה חלקית מלוח הגזירים</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>חלון צומת</translation>
</message>
@@ -519,10 +537,27 @@
<translation>סגירת ארנק</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>סגירת כל הארנקים...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>סגירת כל הארנקים</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>יש להציג את הודעת העזרה של %1 כדי להציג רשימה עם אפשרויות שורת פקודה לביטקוין</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;הסוואת ערכים</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>הסווה את הערכים בלשונית התיאור הכללי
+</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>ארנק בררת מחדל</translation>
</message>
@@ -571,7 +606,7 @@
<message>
<source>Amount: %1
</source>
- <translation>כמות: %1
+ <translation>סכום: %1
</translation>
</message>
<message>
@@ -627,8 +662,12 @@
<translation>הארנק &lt;b&gt;מוצפן&lt;/b&gt; ו&lt;b&gt;נעול&lt;/b&gt; כרגע</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>אירעה שגיאה חמורה. אין אפשרות להשתמש עוד בביטקוין באופן מאובטח והיישום ייסגר.</translation>
+ <source>Original message:</source>
+ <translation>הודעה מקורית:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>אירעה שגיאה חמורה, %1 לא יכול להמשיך בבטחון ולכן יופסק.</translation>
</message>
</context>
<context>
@@ -679,7 +718,7 @@
</message>
<message>
<source>Amount</source>
- <translation>כמות</translation>
+ <translation>סכום</translation>
</message>
<message>
<source>Received with label</source>
@@ -797,7 +836,7 @@
<name>CreateWalletDialog</name>
<message>
<source>Create Wallet</source>
- <translation>צור ארנק.</translation>
+ <translation>יצירת ארנק</translation>
</message>
<message>
<source>Wallet Name</source>
@@ -812,16 +851,32 @@
<translation>הצפנת ארנק</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>נטרלו מפתחות פרטיים לארנק זה. ארנקים עם מפתחות פרטיים מנוטרלים יהיו מחוסרי מפתחות פרטיים וללא מקור HD או מפתחות מיובאים. זהו אידאלי לארנקי צפייה בלבד.</translation>
+ </message>
+ <message>
<source>Disable Private Keys</source>
<translation>השבתת מפתחות פרטיים</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>הכינו ארנק ריק. ארנקים ריקים הנם ללא מפתחות פרטיים ראשוניים או סקריפטים. מפתחות פרטיים או כתובות ניתנים לייבוא, או שניתן להגדיר מקור HD במועד מאוחר יותר. </translation>
+ </message>
+ <message>
<source>Make Blank Wallet</source>
<translation>צור ארנק ריק</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>השתמש ב descriptors לניהול scriptPubKey </translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>ארנק Descriptor </translation>
+ </message>
+ <message>
<source>Create</source>
- <translation>צור</translation>
+ <translation>יצירה</translation>
</message>
</context>
<context>
@@ -895,7 +950,7 @@
</message>
<message>
<source>Path already exists, and is not a directory.</source>
- <translation>הנתיב כבר קיים ואינו מצביע על תיקייה.</translation>
+ <translation>הנתיב כבר קיים ואינו מצביע על תיקיה.</translation>
</message>
<message>
<source>Cannot create data directory here.</source>
@@ -936,6 +991,10 @@
<translation>בעת לחיצה על אישור, %1 יחל בהורדה ועיבוד מלאים של שרשרת המקטעים %4 (%2 ג״ב) החל מההעברות הראשונות ב־%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>חזרה לאחור מהגדרות אלו מחייב הורדה מחדש של כל שרשרת הבלוקים. מהיר יותר להוריד את השרשרת המלאה ולקטום אותה מאוחר יותר. הדבר מנטרל כמה תכונות מתקדמות.</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>הסינכרון הראשוני הוא תובעני ועלול לחשוף בעיות חומרה במחשב שהיו חבויות עד כה. כל פעם שתריץ %1 התהליך ימשיך בהורדה מהנקודה שבה הוא עצר לאחרונה.</translation>
</message>
@@ -945,7 +1004,7 @@
</message>
<message>
<source>Use the default data directory</source>
- <translation>שימוש בבררת המחדל של תיקיית הנתונים.</translation>
+ <translation>שימוש בתיקיית ברירת־המחדל</translation>
</message>
<message>
<source>Use a custom data directory:</source>
@@ -956,8 +1015,12 @@
<translation>ביטקוין</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>התעלם בלוקים לאחר ווריפיקציה, למעט %1 GB המאוחרים ביותר (המקוצצים)</translation>
+ </message>
+ <message>
<source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
- <translation>מידע בנפח של לפחות %1 ג׳יגה-בייט יאוחסן בתיקייה זו, והוא יגדל עם הזמן.</translation>
+ <translation>לפחות %1 ג״ב של נתונים יאוחסנו בתיקייה זו, והם יגדלו עם הזמן.</translation>
</message>
<message>
<source>Approximately %1 GB of data will be stored in this directory.</source>
@@ -1039,6 +1102,10 @@
<translation>Esc</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>%1 מסתנכנים כרגע. תתבצע הורדת כותרות ובלוקים מעמיתים תוך אימותם עד הגעה לראש שרשרת הבלוקים .</translation>
+ </message>
+ <message>
<source>Unknown. Syncing Headers (%1, %2%)...</source>
<translation>לא ידוע. סינכרון כותרות (%1, %2%)...</translation>
</message>
@@ -1108,10 +1175,6 @@
<translation>מראה אם פרוקסי SOCKS5 המסופק כבררת מחדל משמש להתקשרות עם עמיתים באמצעות סוג רשת זה.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>השתמשו בפרוקסי SOCKS&amp;5 נפרד כדי להתקשר עם עמיתים באמצעות שירותים חבויים ברשת Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>הסתר את סמל מגש המערכת</translation>
</message>
@@ -1217,7 +1280,7 @@
</message>
<message>
<source>Proxy &amp;IP:</source>
- <translation>כתובת ה־IP של המ&amp;תווך:</translation>
+ <translation>כתובת ה־&amp;IP של הפרוקסי:</translation>
</message>
<message>
<source>&amp;Port:</source>
@@ -1225,7 +1288,7 @@
</message>
<message>
<source>Port of the proxy (e.g. 9050)</source>
- <translation>הפתחה של המתווך (למשל 9050)</translation>
+ <translation>הפתחה של הפרוקסי (למשל 9050)</translation>
</message>
<message>
<source>Used for reaching peers via:</source>
@@ -1244,10 +1307,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>התחברות לרשת ביטקוין דרך מתווך SOCKS5 נפרד לשירותי Tor נסתרים.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;חלון</translation>
</message>
@@ -1277,7 +1336,7 @@
</message>
<message>
<source>&amp;Unit to show amounts in:</source>
- <translation>י&amp;חידת מידה להצגת כמויות:</translation>
+ <translation>י&amp;חידת מידה להצגת סכומים:</translation>
</message>
<message>
<source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
@@ -1288,6 +1347,14 @@
<translation>האם להציג תכונות שליטת מטבע או לא.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>התחבר לרשת ביטקוין דרך פרוקסי נפרד SOCKS5 proxy לשרותי שכבות בצל (onion services).</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>השתמש בפרוקסי נפרד SOCKS&amp;5 להגעה לעמיתים דרך שרותי השכבות של Tor :</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;כתובות אינטרנט של עסקאות צד שלישי</translation>
</message>
@@ -1404,7 +1471,7 @@
</message>
<message>
<source>Spendable:</source>
- <translation>ניתנים לבזבוז</translation>
+ <translation>ניתנים לבזבוז:</translation>
</message>
<message>
<source>Recent transactions</source>
@@ -1422,6 +1489,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>המאזן הכולל הנוכחי בכתובות לצפייה בלבד</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>מצב הפרטיות הופעל עבור לשונית התאור הכללי. כדי להסיר את הסוואת הערכים, בטל את ההגדרות, -&gt;הסוואת ערכים.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>שיח</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>חתימת עיסקה</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>שידור עיסקה</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>העתקה ללוח הגזירים</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>שמירה...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>סגירה</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>כשלון בטעינת העיסקה: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>כשלון בחתימת העיסקה: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>לא ניתן לחתום קלטים נוספים.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>נחתם קלט %1 אך יש צורך בחתימות נוספות.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>העיסקה נחתמה בהצלחה. העיסקה מוכנה לשידור.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>שגיאה לא מוכרת בעת עיבוד העיסקה.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>העיסקה שודרה בהצלחה! מזהה העיסקה: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>שידור העיסקה נכשל: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT הועתקה ללוח הגזירים.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>שמירת נתוני העיסקה</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>עיסקה חתומה חלקית (בינארי) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT נשמרה לדיסק.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation> * שליחת %1 אל %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>לא מצליח לחשב עמלת עיסקה או הערך הכולל של העיסקה.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>תשלום עמלת עיסקה:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>סכום כולל</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>או</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>לעיסקה יש %1 קלטים לא חתומים.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>לעיסקה חסר חלק מהמידע לגבי הקלטים.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>העיסקה עדיין נזקקת לחתימה(ות).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(אבל ארנק זה לא יכול לחתום על עיסקות.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(אבל לארנק הזה אין את המפתחות המתאימים.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>העיסקה חתומה במלואה ומוכנה לשידור.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>סטטוס העיסקה אינו ידוע.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1442,6 +1636,18 @@
<translation>'//:bitcoin' אינה כתובת URI תקינה. השתמשו במקום ב ':bitcoin'.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>אין אפשרות לעבד את בקשת התשלום כיון ש BIP70 אינו נתמך.</translation>
+ </message>
+ <message>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>עקב תקלות בטיחות רבות ב BIP70 מומלץ בחום להתעלם מההוראות של סוחר להחליף ארנקים </translation>
+ </message>
+ <message>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Iאם קיבלת הודעת שגיאה זו עליך לבקש מבעל העסק לספק URI תואם BIP21 URI.</translation>
+ </message>
+ <message>
<source>Invalid payment address %1</source>
<translation>כתובת תשלום שגויה %1</translation>
</message>
@@ -1451,7 +1657,7 @@
</message>
<message>
<source>Payment request file handling</source>
- <translation>טיפול בקבצי בקשות תשלום</translation>
+ <translation>טיפול בקובצי בקשות תשלום</translation>
</message>
</context>
<context>
@@ -1485,7 +1691,7 @@
<name>QObject</name>
<message>
<source>Amount</source>
- <translation>כמות</translation>
+ <translation>סכום</translation>
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
@@ -1576,6 +1782,10 @@
<translation>שגיאה: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>שגיאה בהגדרות הראשוניות: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>הסגירה של %1 לא הושלמה בהצלחה עדיין…</translation>
</message>
@@ -1643,7 +1853,7 @@
</message>
<message>
<source>To specify a non-default location of the data directory use the '%1' option.</source>
- <translation>כדי לשנות את מיקום תיקית הנתונים יש להשתמש באופצית '%1' .</translation>
+ <translation>כדי לציין מיקום שאינו ברירת המחדל לתיקיית הבלוקים יש להשתמש באפשרות "%1"</translation>
</message>
<message>
<source>Blocksdir</source>
@@ -1651,7 +1861,7 @@
</message>
<message>
<source>To specify a non-default location of the blocks directory use the '%1' option.</source>
- <translation>כדי לשנות את מיקום תיקית הבלוקים יש להשתמש באופצית '%1' .</translation>
+ <translation>כדי לציין מיקום שאינו ברירת המחדל לתיקיית הבלוקים יש להשתמש באפשרות "%1"</translation>
</message>
<message>
<source>Startup time</source>
@@ -1674,10 +1884,6 @@
<translation>שרשרת מקטעים</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>מספר המקטעים הנוכחי</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>מאגר זכרון</translation>
</message>
@@ -1722,10 +1928,6 @@
<translation>נא לבחור בעמית כדי להציג מידע מפורט.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>ברשימה הלבנה</translation>
- </message>
- <message>
<source>Direction</source>
<translation>כיוון</translation>
</message>
@@ -1746,6 +1948,10 @@
<translation>בלוקים מסונכרנים</translation>
</message>
<message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation>המערכת האוטונומית הממופה משמשת לגיוון בחירת עמיתים.</translation>
+ </message>
+ <message>
<source>Mapped AS</source>
<translation>מופה בתור</translation>
</message>
@@ -1758,8 +1964,12 @@
<translation>חלון צומת</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>גובה הבלוק הנוכחי</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>פתחו את לוג ניפוי השגיאות ה%1 מתיקיית הנתונים הנוכחית. עבור קבצי לוג גדולים ייתכן זמן המתנה של מספר שניות.</translation>
+ <translation>פתיחת יומן ניפוי הבאגים %1 מתיקיית הנתונים הנוכחית. עבור קובצי יומן גדולים ייתכן זמן המתנה של מספר שניות.</translation>
</message>
<message>
<source>Decrease font size</source>
@@ -1770,12 +1980,12 @@
<translation>הגדל גודל גופן</translation>
</message>
<message>
- <source>Services</source>
- <translation>שירותים</translation>
+ <source>Permissions</source>
+ <translation>הרשאות</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>דירוג חסימה</translation>
+ <source>Services</source>
+ <translation>שירותים</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1926,14 +2136,6 @@
<translation>תעבורה יוצאת</translation>
</message>
<message>
- <source>Yes</source>
- <translation>כן</translation>
- </message>
- <message>
- <source>No</source>
- <translation>לא</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>לא ידוע</translation>
</message>
@@ -1969,6 +2171,14 @@
<translation>סכום כרשות לבקשה. ניתן להשאיר זאת ריק כדי לא לבקש סכום מסוים.</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>תווית אופצינלית לצירוף לכתובת קבלה חדשה (לשימושך לזיהוי חשבונות). היא גם מצורפת לבקשת התשלום.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>הודעה אוצפציונלית מצורפת לבקשת התשלום אשר ניתן להציגה לשולח.</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
<translation>&amp;יצירת כתובת קבלה חדשה</translation>
</message>
@@ -2024,56 +2234,60 @@
<source>Copy amount</source>
<translation>העתקת הסכום</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>לא ניתן לשחרר את הארנק.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>לא ניתן לייצר כתובת %1 חדשה</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>קוד QR</translation>
+ <source>Request payment to ...</source>
+ <translation>בקשת תשלום לטובת…</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>העתקת &amp;כתובת משאב</translation>
+ <source>Address:</source>
+ <translation>כתובת:</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>העתקת &amp;כתובת</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;שמירת תמונה…</translation>
+ <source>Amount:</source>
+ <translation>סכום:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>בקשת תשלום אל %1</translation>
+ <source>Label:</source>
+ <translation>תוית:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>פרטי תשלום</translation>
+ <source>Message:</source>
+ <translation>הודעה:</translation>
</message>
<message>
- <source>URI</source>
- <translation>כתובת</translation>
+ <source>Wallet:</source>
+ <translation>ארנק:</translation>
</message>
<message>
- <source>Address</source>
- <translation>כתובת</translation>
+ <source>Copy &amp;URI</source>
+ <translation>העתקת &amp;כתובת משאב</translation>
</message>
<message>
- <source>Amount</source>
- <translation>סכום</translation>
+ <source>Copy &amp;Address</source>
+ <translation>העתקת &amp;כתובת</translation>
</message>
<message>
- <source>Label</source>
- <translation>תוית</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;שמירת תמונה…</translation>
</message>
<message>
- <source>Message</source>
- <translation>הודעה</translation>
+ <source>Request payment to %1</source>
+ <translation>בקשת תשלום אל %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>ארנק</translation>
+ <source>Payment information</source>
+ <translation>פרטי תשלום</translation>
</message>
</context>
<context>
@@ -2119,7 +2333,7 @@
</message>
<message>
<source>Inputs...</source>
- <translation>קלטים…</translation>
+ <translation>קלט...</translation>
</message>
<message>
<source>automatically selected</source>
@@ -2175,7 +2389,7 @@
</message>
<message>
<source>Warning: Fee estimation is currently not possible.</source>
- <translation>אזהרה</translation>
+ <translation>אזהרה: שערוך העמלה לא אפשרי כעת.</translation>
</message>
<message>
<source>Specify a custom fee per kB (1,000 bytes) of the transaction's virtual size.
@@ -2295,7 +2509,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Cr&amp;eate Unsigned</source>
- <translation>יצ&amp;ירת לא חתום</translation>
+ <translation>י&amp;צירת לא חתומה</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>
@@ -2322,6 +2536,22 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>לשלוח?</translation>
</message>
<message>
+ <source>Create Unsigned</source>
+ <translation>יצירת לא חתומה</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>שמירת נתוני העיסקה</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>עיסקה חתומה חלקית (בינארי) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT נשמרה</translation>
+ </message>
+ <message>
<source>or</source>
<translation>או</translation>
</message>
@@ -2330,6 +2560,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>תוכלו להגדיל את העמלה מאוחר יותר (איתות 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>
+ <translation>בבקשה לסקור את העיסקה המוצעת. הדבר יצור עיסקת ביטקוין חתומה חלקית (PSBT) אשר ניתן לשמור או להעתיק ואז לחתום עם למשל ארנק לא מקוון %1, או עם ארנק חומרה תואם-PSBT.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>אנא עברו שוב על העסקה שלכם.</translation>
</message>
@@ -2346,20 +2580,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>סכום כולל</translation>
</message>
<message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>כדי לסקור את רשימת המקבלים יש להקיש "הצגת פרטים..."</translation>
+ </message>
+ <message>
<source>Confirm send coins</source>
<translation>אימות שליחת מטבעות</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>העתקת PSBT אל לוח הגזירים</translation>
+ <source>Confirm transaction proposal</source>
+ <translation>אישור הצעת עיסקה</translation>
</message>
<message>
<source>Send</source>
- <translation>שלח</translation>
- </message>
- <message>
- <source>PSBT copied</source>
- <translation>PSBT הועתקה</translation>
+ <translation>שליחה</translation>
</message>
<message>
<source>Watch-only balance:</source>
@@ -2461,6 +2695,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>הסרת רשומה זו</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>הסכום לשליחה במטבע הנבחר</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>העמלה תנוכה מהסכום שנשלח. הנמען יקבל פחות ביטקוינים ממה שהזנת בשדה הסכום. אם נבחרו מספר נמענים, העמלה תחולק באופן שווה.</translation>
</message>
@@ -2560,7 +2798,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>ניתן לחתום על ההודעה כדי להוכיח שכתובת הביטקוין הזו בבעלותך.</translation>
+ <translation>ניתן לחתום על ההודעה כדי להוכיח שכתובת ביטקוין זו בבעלותך</translation>
</message>
<message>
<source>Sign &amp;Message</source>
@@ -2591,6 +2829,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>ההודעה החתומה לאימות</translation>
</message>
<message>
+ <source>The signature given when the message was signed</source>
+ <translation>החתימה שניתנת כאשר ההודעה נחתמה</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>ניתן לאמת את ההודעה כדי להבטיח שהיא נחתמה עם כתובת הביטקוין הנתונה</translation>
</message>
@@ -3091,11 +3333,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Exporting Failed</source>
- <translation>יצוא נכשל</translation>
+ <translation>הייצוא נכשל</translation>
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
- <translation>אירעה שגיאה בעת ניסיון שמירת היסטוריית ההעברות אל %1.</translation>
+ <translation>הייתה שגיאה בניסיון לשמור את היסטוריית העסקאות אל %1.</translation>
</message>
<message>
<source>Exporting Successful</source>
@@ -3103,7 +3345,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>The transaction history was successfully saved to %1.</source>
- <translation>היסטוריית ההעברות נשמרה בהצלחה אל %1.</translation>
+ <translation>היסטוריית העסקאות נשמרה בהצלחה אל %1.</translation>
</message>
<message>
<source>Range:</source>
@@ -3129,18 +3371,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
- <translation>האם את/ה בטוח/ה שברצונך לסגור את הארנק &lt;i&gt;%1&lt;/i&gt;?</translation>
+ <translation>האם אכן ברצונך לסגור את הארנק &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>סגירת הארנק למשך זמן רב מדי יכול לגרור את הצורך לסינכרון מחדש של כל השרשרת אם אופצית הגיזום אקטיבית.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>סגירת כל הארנקים</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>האם אכן ברצונך לסגור את כל הארנקים?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>לא נטען ארנק.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>לא נטען ארנק.
+עליך לגשת לקובץ &gt; פתיחת ארנק כדי לטעון ארנק.
+- או -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>יצירת ארנק חדש</translation>
</message>
</context>
<context>
@@ -3162,6 +3420,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>האם ברצונך להגדיל את העמלה?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>האם ברצונך להכין עסיקה עם עמלה מוגברת?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>העמלה הנוכחית:</translation>
</message>
@@ -3209,6 +3471,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>יצוא הנתונים בלשונית הנוכחית לקובץ</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>שגיאה</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>לא ניתן לפענח PSBT מתוך לוח הגזירים (base64 שגוי) </translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>טעינת נתוני עיסקה</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>עיסקה חתומה חלקית (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>קובץ PSBT צריך להיות קטמן מ 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>לא מצליח לפענח PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>גיבוי הארנק</translation>
</message>
@@ -3252,10 +3538,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>גיזום: הסינכרון האחרון של הארנק עובר את היקף הנתונים שנגזמו. יש לבצע חידוש אידקסציה (נא להוריד את כל שרשרת הבלוקים שוב במקרה של צומת מקוצצת)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>שגיאה: סניה קלמה קריטית פנימית קרטה, פנה ל debug.log לפרטים</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>מקצץ את ה blockstore...</translation>
</message>
@@ -3268,14 +3550,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>ה %s מפתחים</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>לא מצליח ליצור מפתח שינוי כתובת. אין מפתחות במאגר הפנימי של המפתחות ולא מצליח ליצור מפתח כלשהו.</translation>
- </message>
- <message>
- <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
- <translation>לא מצליח לנעול את תיקית הנתונים %s. %s כנראה כבר רץ.</translation>
- </message>
- <message>
<source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
<translation>לא מצליח לספק קשרים ספציפיים ולגרום ל addrman למצוא קשרים חיצוניים יחדיו.</translation>
</message>
@@ -3297,7 +3571,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>קוד זה הינו גרסת טסט טרום-פרסומית. *שימוש על אחריותכם בלבד* אין לעשות שימוש בקוד לצרכי כריית בלוקים או אפליקציות מסחר.</translation>
+ <translation>זוהי בניית ניסיון טרום־פרסום – השימוש באחריותך – אין להשתמש בה לצורך כרייה או יישומי מסחר</translation>
</message>
<message>
<source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
@@ -3320,14 +3594,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>אזהרה: יתכן שלא נסכים לגמרי עם עמיתינו! יתכן שתצטרכו לשדרג או שצמתות אחרות יצטרכו לשדרג.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d מ 100 הבלוקים האחרונים הנם בעלי גירסה לא צפויה.</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s משובש. נסיון החילוץ נכשל.</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>‎-maxmempool חייב להיות לפחות %d מ״ב</translation>
</message>
@@ -3349,7 +3615,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Corrupted block database detected</source>
- <translation>התגלה מסד נתוני מקטעים לא תקין</translation>
+ <translation>מסד נתוני בלוקים פגום זוהה</translation>
+ </message>
+ <message>
+ <source>Could not find asmap file %s</source>
+ <translation> קובץ asmap %s לא נמצא</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation> קובץ asmap %s לא נפרס</translation>
</message>
<message>
<source>Do you want to rebuild the block database now?</source>
@@ -3373,7 +3647,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Error loading %s: Wallet corrupted</source>
- <translation>שגיאת טעינה %s: הארנק משובש.</translation>
+ <translation>שגיאת טעינה %s: הארנק משובש</translation>
</message>
<message>
<source>Error loading %s: Wallet requires newer version of %s</source>
@@ -3417,7 +3691,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
- <translation>סכום לא תקין של -discardfee=&lt;amount&gt;: '%s'</translation>
+ <translation>סכום שגוי של -discardfee=&lt;amount&gt;‏: '%s'</translation>
</message>
<message>
<source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
@@ -3444,11 +3718,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>טעינת כתובות P2P...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>שגיאה: שטח הדיסק נמוך מדי!
- </translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>טוען רשימת חסומים...</translation>
</message>
@@ -3502,7 +3771,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Verifying blocks...</source>
- <translation>המקטעים מאומתים…</translation>
+ <translation>באימות הבלוקים…</translation>
</message>
<message>
<source>Wallet needed to be rewritten: restart %s to complete</source>
@@ -3513,18 +3782,46 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>שגיאה: האזנה לתקשורת נכנ סת נכשלה (ההאזנה מחזירה שגיאה %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>כמות שגויה של -maxtxfee=&lt;amount&gt;: '%s' (נדרש לפחות minrelay עמלה של %s כדי למנוע עסקאות מלהתקע</translation>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s משובש. נסו להשתמש בכלי הארנק bitcoin-wallet כדי להציל או לשחזר מגיבוי..</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>אין אפשרות לשדרג ארנק מפוצל שאינו HD מבלי לתמוך במאגר המפתחות טרם הפיצול. בבקשה להשתמש בגירסת 169900 או שלא צויינה גירסה.</translation>
</message>
<message>
<source>The transaction amount is too small to send after the fee has been deducted</source>
<translation>סכום העברה נמוך מדי לשליחה אחרי גביית העמלה</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>שגיאה זו יכלה לקרות אם הארנק לא נסגר באופן נקי והועלה לאחרונה עם מבנה מבוסס גירסת Berkeley DB חדשה יותר. במקרה זה, יש להשתמש בתוכנה אשר טענה את הארנק בפעם האחרונה.</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>זוהי עמלת העיסקה המרבית שתשלם (בנוסף לעמלה הרגילה) כדי לתעדף מניעת תשלום חלקי על פני בחירה רגילה של מטבע. </translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>עיסקה מחייבת שינוי כתובת, אך לא ניתן לייצרה. נא לקרוא תחילה ל keypoolrefill </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>יש צורך בבניה מחדש של מסד הנתונים ע"י שימוש ב -reindex כדי לחזור חזרה לצומת שאינה גזומה. הפעולה תוריד מחדש את כל שרשרת הבלוקים.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>שגיאה פטלית פנימית אירעה, לפירוט ראה את לוג הדיבאג.</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>לא מצליח להגדיר את -peerblockfilters ללא-blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>אין מספיק מקום בכונן!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>שגיאת קריאה ממסד הנתונים. סוגר את התהליך.</translation>
</message>
@@ -3537,6 +3834,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>שגיאה: שטח הדיסק קטן מדי עובר %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>שגיאה: Keypool עבר את המכסה, קרא תחילה ל keypoolrefill </translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>שיעור העמלה (%s) נמוך משיעור העמלה המינימלי המוגדר (%s)</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>אי תקינות כתובת -onion או hostname: '%s'</translation>
</message>
@@ -3546,7 +3851,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
- <translation>כמות לא תקינה עבור ‎-paytxfee=&lt;amount&gt;‎:‏ '%s' (חייבת להיות לפחות %s)</translation>
+ <translation>סכום שגוי של ‎-paytxfee=&lt;amount&gt;‏‎:‏‏ '%s' (נדרשת %s לפחות)</translation>
</message>
<message>
<source>Invalid netmask specified in -whitelist: '%s'</source>
@@ -3554,7 +3859,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Need to specify a port with -whitebind: '%s'</source>
- <translation>עליך לציין פתחה עם ‎-whitebind:‏ '%s'</translation>
+ <translation>יש לציין פתחה עם ‎-whitebind:‏ '%s'</translation>
+ </message>
+ <message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>לא הוגדר פרוקסי. יש להשתמש ב־‎ -proxy=&lt;ip&gt; או ב־‎ -proxy=&lt;ip:port&gt;.</translation>
</message>
<message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
@@ -3582,7 +3891,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Specified -walletdir "%s" is not a directory</source>
- <translation>תיקיית הארנק שצויינה -walletdir "%s" אינה תיקייה</translation>
+ <translation>תיקיית הארנק שצויינה -walletdir‏ "%s" אינה תיקיה</translation>
</message>
<message>
<source>The specified config file %s does not exist
@@ -3612,25 +3921,25 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Unable to create the PID file '%s': %s</source>
- <translation>לא מצליח ליצור את קובץ PID '%s': %s</translation>
+ <translation>לא ניתן ליצור את קובץ PID‏ '%s':‏ %s</translation>
</message>
<message>
<source>Unable to generate initial keys</source>
- <translation>לא מצליח ליצור מפתחות ראשוניים</translation>
+ <translation>לא ניתן ליצור מפתחות ראשוניים</translation>
+ </message>
+ <message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>ערך -blockfilterindex %s לא ידוע.</translation>
</message>
<message>
<source>Verifying wallet(s)...</source>
- <translation>מאמת ארנק(ים)...</translation>
+ <translation>באימות הארנק(ים)...</translation>
</message>
<message>
<source>Warning: unknown new rules activated (versionbit %i)</source>
<translation>אזהרה: חוקים חדשים שאינם מוכרים שופעלו (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>שולה את כל העסקאות מתוך הארנק...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee נקבע לעמלות גבוהות מאד! עמלות גבוהות כאלו יכולות משולמות עבר עסקה בודדת.</translation>
</message>
@@ -3643,10 +3952,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>האורך הכולל של רצף התווים של גירסת הרשת (%i) גדול מהאורך המרבי המותר (%i). יש להקטין את המספר או האורך של uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>אזהרה: הארנק משובש. הנתונים חולצו! המקור %s נשמר כ %s ב %s; אם היתרהאו העסקות אינן נכונות יש לבצע שיחזור מגיבוי.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s הוגדר מאד גבוה!</translation>
</message>
@@ -3691,10 +3996,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>אין מספיק כספים</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>אין אפשרות לבצע שדרוג של ארנק מפוצל שאינו HD ללא שדרוג לתמיכה של טרום פיצול של keypool .יש להשתמש ב -upgradewallet=169900 או -upgradewallet ללא ציון גירסה.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>אמדן גובה עמלה נכשל. Fallbackfee  מנוטרל. יש להמתין מספר בלוקים או לשפעל את -fallbackfee</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hi.ts b/src/qt/locale/bitcoin_hi.ts
index 841d2ca4dd..086a106c3d 100644
--- a/src/qt/locale/bitcoin_hi.ts
+++ b/src/qt/locale/bitcoin_hi.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>एड्रेस या लेबल को बदलने के लिए राइट-क्लिक करें </translation>
+ <translation>पता व नामपत्र बदलने के लिए दायीं कुंजी दबाइए </translation>
</message>
<message>
<source>Create a new address</source>
@@ -70,10 +70,6 @@
<translation>भुगतान करने के लिए ये आपके बिटकॉइन एड्रेस हैं। कॉइन भेजने से पहले राशि और गंतव्य एड्रेस की हमेशा जाँच करें </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.</source>
- <translation>भुगतान प्राप्त करने के लिए ये आपके बिटकॉइन एड्रेस हैं। नया एड्रेस बनाने के लिए रिसीव टैब में 'नया एड्रेस बनाएं' बटन का प्रयोग करें</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;एड्रेस कॉपी करें</translation>
</message>
@@ -323,6 +319,10 @@
<translation>तिजोरी</translation>
</message>
<message>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>इस पते पर बिटकौइन भेजें</translation>
+ </message>
+ <message>
<source>Change the passphrase used for wallet encryption</source>
<translation>पहचान शब्द/अक्षर जो वॉलेट एनक्रिपशन के लिए इस्तेमाल किया है उसे बदलिए!</translation>
</message>
@@ -363,6 +363,22 @@
<translation>नवीनतम</translation>
</message>
<message>
+ <source>Open a wallet</source>
+ <translation>बटुआ खोलें</translation>
+ </message>
+ <message>
+ <source>Close Wallet...</source>
+ <translation>बटुआ बंद करें...</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation>बटुआ बंद करें</translation>
+ </message>
+ <message>
+ <source>Close All Wallets...</source>
+ <translation>सारे बटुएँ बंद करें...</translation>
+ </message>
+ <message>
<source>Sent transaction</source>
<translation>भेजी ट्रांजक्शन</translation>
</message>
@@ -382,6 +398,10 @@
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Quantity:</source>
+ <translation>मात्रा :</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>राशि :</translation>
</message>
@@ -398,6 +418,14 @@
<translation>पक्का</translation>
</message>
<message>
+ <source>yes</source>
+ <translation>हाँ</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>नहीं</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(कोई परचा नहीं )</translation>
</message>
@@ -488,6 +516,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -538,26 +569,18 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;पता कॉपी करे</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>पता</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>राशि</translation>
+ <source>Amount:</source>
+ <translation>राशि :</translation>
</message>
<message>
- <source>Label</source>
- <translation>परचा</translation>
+ <source>Wallet:</source>
+ <translation>तिजोरी</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>वॉलेट</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;पता कॉपी करे</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -580,6 +603,10 @@
<translation>सिक्के भेजें|</translation>
</message>
<message>
+ <source>Quantity:</source>
+ <translation>मात्रा :</translation>
+ </message>
+ <message>
<source>Amount:</source>
<translation>राशि :</translation>
</message>
@@ -733,6 +760,10 @@
</context>
<context>
<name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>बटुआ बंद करें</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
@@ -754,6 +785,10 @@
<source>Export the data in the current tab to a file</source>
<translation>डेटा को मौजूदा टैब से एक फ़ाइल में निर्यात करें</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>भूल</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_hr.ts b/src/qt/locale/bitcoin_hr.ts
index 0d0a2e6765..98c1abaab5 100644
--- a/src/qt/locale/bitcoin_hr.ts
+++ b/src/qt/locale/bitcoin_hr.ts
@@ -7,7 +7,7 @@
</message>
<message>
<source>Create a new address</source>
- <translation>Dodajte novu adresu</translation>
+ <translation>Stvoriti novu adresu</translation>
</message>
<message>
<source>&amp;New</source>
@@ -70,10 +70,6 @@
<translation>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.</source>
- <translation>Ovo su vaše Bitcoin adrese za primanje novca. Preporučeno je da koristite novu primateljsku adresu za svaku transakciju.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopirajte adresu</translation>
</message>
@@ -616,11 +612,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Novčanik je &lt;b&gt;šifriran&lt;/b&gt; i trenutno &lt;b&gt;zaključan&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Dogodila se kobna greška. Bitcoin ne može više sigurno nastaviti te će se zatvoriti.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1118,10 +1110,6 @@
<translation>Prikazuje se ako je isporučeni uobičajeni SOCKS5 proxy korišten radi dohvaćanja klijenata preko ovog tipa mreže.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Koristite zaseban SOCKS&amp;5 proxy kako biste dohvatili klijente preko Tora:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Sakrijte ikonu sa sustavne trake.</translation>
</message>
@@ -1254,10 +1242,6 @@
<translation>Tora</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Spojite se na Bitcoin mrežu kroz zaseban SOCKS5 proxy za povezivanje na Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Prozor</translation>
</message>
@@ -1432,7 +1416,22 @@
<source>Current total balance in watch-only addresses</source>
<translation>Trenutno ukupno stanje na isključivo promatranim adresama</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dijalog</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Ukupni iznos</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ili</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1692,10 +1691,6 @@
<translation>Lanac blokova</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Trenutni broj blokova</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memorijski bazen</translation>
</message>
@@ -1740,10 +1735,6 @@
<translation>Odaberite klijent kako biste vidjeli detaljne informacije.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Na bijeloj listi</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Smjer</translation>
</message>
@@ -1784,10 +1775,6 @@
<translation>Usluge</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Broj zabrana</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Trajanje veze</translation>
</message>
@@ -1936,14 +1923,6 @@
<translation>Izlazni</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ne</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Nepoznato</translation>
</message>
@@ -2034,12 +2013,28 @@
<source>Copy amount</source>
<translation>Kopiraj iznos</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Ne može se otključati novčanik.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR kôd</translation>
+ <source>Amount:</source>
+ <translation>Iznos:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Oznaka</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Poruka:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Novčanik:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2061,30 +2056,6 @@
<source>Payment information</source>
<translation>Informacije o uplati</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Iznos</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Oznaka</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Poruka</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Novčanik</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2232,6 +2203,11 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Prah:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>Sakrijte postavke za transakcijske provizije
+</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>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>
@@ -2447,6 +2423,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Obrišite ovaj zapis</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>Iznos za slanje u odabranoj valuti </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>Naknada će biti oduzeta od poslanog iznosa. Primatelj će primiti manji iznos od onoga koji unesete u polje iznosa. Ako je odabrano više primatelja, onda će naknada biti podjednako raspodijeljena.</translation>
</message>
@@ -3117,12 +3097,12 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Držanje novčanik zatvorenim predugo može rezultirati ponovnom sinkronizacijom cijelog lanca ako je obrezivanje uključeno.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nije pokrenut nikakav novčanik.</translation>
+ <source>Create a new wallet</source>
+ <translation>Stvorite novi novčanik</translation>
</message>
</context>
<context>
@@ -3183,6 +3163,10 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Izvoz podataka iz trenutnog lista u datoteku</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Greška</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Arhiviranje novčanika</translation>
</message>
@@ -3226,10 +3210,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>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>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Greška: Dogodila se kobna interna greška. Vidite debug.log za detalje</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Obrezuje se blockstore...</translation>
</message>
@@ -3242,10 +3222,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Ekipa %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Ne može se generirati ključ adrese za ostatak. Nema ključeva u unutarnjem bazenu ključeva i ne mogu se generirati nikakvi ključevi.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Program ne može pristupiti podatkovnoj mapi %s. %s je vjerojatno već pokrenut.</translation>
</message>
@@ -3294,14 +3270,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>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>%d of last 100 blocks have unexpected version</source>
- <translation>%d od zadnjih 100 blokova ima neočekivanu verziju</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s pokvaren, spašavanje neuspješno</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool mora biti barem %d MB</translation>
</message>
@@ -3418,10 +3386,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Pokreće se popis P2P adresa...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Pogreška: Nema dovoljno prostora na disku!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Pokreće se popis zabrana...</translation>
</message>
@@ -3604,10 +3568,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Upozorenje: nepoznata nova pravila aktivirana (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Brišu se sve transakcije iz novčanika...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee je postavljen preveliko. Naknade ove veličine će biti plaćene na individualnoj transakciji.</translation>
</message>
@@ -3620,10 +3580,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Ukupna duljina stringa verzije mreže (%i) prelazi maksimalnu duljinu (%i). Smanjite broj ili veličinu komentara o korisničkom agentu (uacomments).</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Upozorenje: Datoteka novčanika je pokvarena, ali su podaci spašeni! Original %s snimljen je kao %s u %s; ako su transakcije ili stanje neispravni, onda biste trebali restorirati sa sigurnosne kopije (backupa).</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s je postavljen preveliko!</translation>
</message>
@@ -3668,10 +3624,6 @@ Napomena: Budući da se naknada računa po bajtu, naknada od "100 satošija po k
<translation>Nedovoljna sredstva</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Ne može se ažurirati novčanik koji nije HD bez ažuriranja radi podrške za bazen ključeva prije raskola. Molim koristite -upgradewallet=169900 ili -upgradewallet bez zadane verzije.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Neuspješno procjenjivanje naknada. Fallbackfee je isključena. Pričekajte nekoliko blokova ili uključite -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_hu.ts b/src/qt/locale/bitcoin_hu.ts
index e8c13c3c27..ccc860b7d2 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>A cím vagy címke szerkesztéséhez kattints a jobb gombbal</translation>
+ <translation>Cím vagy címke szerkesztéséhez kattints a jobb gombbal</translation>
</message>
<message>
<source>Create a new address</source>
@@ -59,19 +59,20 @@
</message>
<message>
<source>Sending addresses</source>
- <translation>Küldési cím</translation>
+ <translation>Küldési címek</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>Fogadási cím</translation>
+ <translation>Fogadási címek</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>Ezek a Bitcoin címeid kifizetések küldéséhez. Mindíg ellenőrizd az összeget és a fogadó címet mielőtt coinokat küldenél.</translation>
+ <translation>Ezek a te Bitcoin címeid kifizetések küldéséhez. Mindíg ellenőrizd az összeget és a fogadó címet mielőtt coinokat küldenél.</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.</source>
- <translation>Ezek a fizetések fogadására szolgáló Bitcoin-címeid. Használd az "Új fogadócím létrehozása" gombot a fogadás fülön új cím létrehozásához.</translation>
+ <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>Ezek a Bitcoin címeid amelyeken fogadni tudsz Bitcoin utalásokat. Az "Új cím létrehozása" gombbal tudsz új címet létrehozni. Aláírni csak korábbi egyessel kezdődő címekkel lehet.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -83,7 +84,7 @@
</message>
<message>
<source>&amp;Edit</source>
- <translation>Szerkesztés</translation>
+ <translation>&amp;Szerkesztés</translation>
</message>
<message>
<source>Export Address List</source>
@@ -482,6 +483,22 @@
<translation>Naprakész</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;PSBT betöltése fájlból.</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Részlegesen aláírt Bitcoin tranzakció (PSBT) betöltése</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>PSBT betöltése vágólapról</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Részlegesen aláírt Bitcoin tranzakció (PSBT) betöltése vágólapról</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Csomópont ablak</translation>
</message>
@@ -498,6 +515,10 @@
<translation>&amp;Fogadó címek</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Bitcoin URI megnyitása</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Tárca megnyitása</translation>
</message>
@@ -514,10 +535,26 @@
<translation>Tárca bezárása</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Összes tárca bezárása...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Összes tárca bezárása</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>A %1 súgó megjelenítése a Bitcoin lehetséges parancssori kapcsolóinak listájával</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Értékek elrejtése</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Értékek elrejtése az Áttekintés fülön</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>Alapértelmezett tárca</translation>
</message>
@@ -625,8 +662,12 @@
<translation>A tárca &lt;b&gt;titkosítva&lt;/b&gt; és jelenleg &lt;b&gt;bezárva&lt;/b&gt;.</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Végzetes hiba történt. A Bitcoin működése nem biztonságos és hamarosan leáll.</translation>
+ <source>Original message:</source>
+ <translation>Eredeti üzenet:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Végzetes hiba történt %1 nem tud biztonságban továbblépni így most kilép.</translation>
</message>
</context>
<context>
@@ -830,6 +871,14 @@
<translation>Üres tárca készítése</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Leírók használata scriptPubKey menedzseléshez</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Descriptor Tárca</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Létrehozás</translation>
</message>
@@ -873,6 +922,14 @@
<translation>A megadott "%1" cím nem egy érvényes Bitcoin-cím.</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>A(z) "%1" már egy létező fogadó cím "%2" névvel és nem lehet küldő címként hozzáadni.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>A megadott "%1" cím már szerepel a címjegyzékben "%2" néven.</translation>
+ </message>
+ <message>
<source>Could not unlock wallet.</source>
<translation>Nem sikerült a tárca megnyitása</translation>
</message>
@@ -993,7 +1050,15 @@
<source>%n GB of free space available</source>
<translation><numerusform>%n GB elérhető szabad hely</numerusform><numerusform>%n GB elérhető szabad hely</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(of %n GB needed)</source>
+ <translation><numerusform>(%n GB szükségesnek)</numerusform><numerusform>(%n GB szükségesnek)</numerusform></translation>
+ </message>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(%n GB szükséges a teljes lánchoz)</numerusform><numerusform>(%n GB szükséges a teljes lánchoz)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -1044,7 +1109,15 @@
<source>Esc</source>
<translation>Kilépés</translation>
</message>
- </context>
+ <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>%1 szinkronizálás alatt. Fejléceket és blokkokat tölt le a felektől, majd érvényesíti, amíg el nem éri a blokklánc tetejét.</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>Ismeretlen. Fejlécek szinkronizálása (%1, %2%)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
<message>
@@ -1110,10 +1183,6 @@
<translation>Megmutatja, hogy az alapértelmezett SOCKS5 proxy van-e használatban, hogy elérje a párokat ennél a hálózati típusnál.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Za dostop do soležnikov preko skritih storitev Tor uporabi drug posredniški strežnik SOCKS&amp;5:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Ikon elrejtése a tálcáról.</translation>
</message>
@@ -1246,10 +1315,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Csatlakozás a Bitcoin hálózathoz külön SOCKS5 proxy használatával a Tor rejtett szolgáltatásainak eléréséhez.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Ablak</translation>
</message>
@@ -1290,10 +1355,18 @@
<translation>Mutassa a pénzküldés beállításait vagy ne.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Csatlakozás a Bitcoin hálózathoz külön SOCKS5 proxy használatával a Tor rejtett szolgáltatásainak eléréséhez.</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;Harmadik féltől származó tranzakció URL-ek</translation>
</message>
<message>
+ <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
+ <translation>Az ebben a párbeszédablakban beállított opciók felülírásra kerültek a parancssor által vagy a konfigurációs fájlban:</translation>
+ </message>
+ <message>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
</message>
@@ -1420,6 +1493,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>A csak megfigyelt címek jelenlegi teljes egyenlege</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Diszkrét mód aktiváva az áttekintés fülün. Az értékek újbóli megjelenítéséhez kapcsold ki a Beállítások-&gt;Értékek maszkolását</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Párbeszéd</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Tx aláírása</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Tx kiküldése</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Másolás vágólapra</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Mentés...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Bezárás</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Tranzakció betöltése sikertelen: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Tranzakció aláírása sikertelen: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Több input-ot nem tudok aláírni.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>%1 input aláírva, de több alárásra van szükség.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Tranzakció sikeresen aláírva. Szétküldésre kész.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Imseretlen hiba a tranzakció feldolázásakor.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Tranzakció sikeresen szétküldve. Transaction ID: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Tranzakció szétküldése sikertelen: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT vágólapra másolva.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Tranzakció adatainak mentése</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Részlegesen Aláírt Tranzakció (PSBT bináris) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT háttértárolóra mentve.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation> * Küldés %1 to %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Nem tudok tranzakciós díjat vagy teljes tranzakció értéket kalkulálni.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Fizetendő tranzakciós díj:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Teljes összeg</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>vagy</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>A tranzakciónak %1 aláíratlan bejövő érteke van.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>A tranzakcióból adatok hiányoznak a bejövő oldalon.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Még aláírások szükségesen a tranzakcióhoz.</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(De ez a tárca nem tudja aláírni a tranzakciókat.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(De ebben a tárcában nincsenek meg a megfelelő kulcsok.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Tranzakció teljesen aláírva és szétküldésre kész.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Tranzakció állapota ismeretlen.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1440,10 +1640,18 @@
<translation>'bitcoin://' nem érvényes egységes erőforrás azonosító (URI). Használd helyette a 'bitcoin'-t.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>A fizetési kérelmet nem lehet feldolgozni, mert a BIP70 nem támogatott.</translation>
+ </message>
+ <message>
<source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
<translation>A BIP70 széleskörű biztonsági hiányosságai következtében határozottan ajánljuk, hogy hagyjon figyelmen kívül bármiféle kereskedelmi utasítást, amely a tárca váltására készteti.</translation>
</message>
<message>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>Ha ezt a hibaüzenetet kapod, meg kell kérned a kereskedőt, hogy biztosítson BIP21 kompatibilis URI-t.</translation>
+ </message>
+ <message>
<source>Invalid payment address %1</source>
<translation>Érvénytelen fizetési cím %1</translation>
</message>
@@ -1578,6 +1786,10 @@
<translation>Hiba: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Beállítások betöltése sikertelen: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 még nem lépett ki biztonságosan...</translation>
</message>
@@ -1644,10 +1856,18 @@
<translation>Adatkönyvtár</translation>
</message>
<message>
+ <source>To specify a non-default location of the data directory use the '%1' option.</source>
+ <translation>Az adat könyvárhoz kívánt nem alapértelmezett elérési úthoz használd a '%1' opciót</translation>
+ </message>
+ <message>
<source>Blocksdir</source>
<translation>Blokk könyvtár</translation>
</message>
<message>
+ <source>To specify a non-default location of the blocks directory use the '%1' option.</source>
+ <translation>Az blokkk könyvárhoz kívánt nem alapértelmezett elérési úthoz használd a '%1' opciót</translation>
+ </message>
+ <message>
<source>Startup time</source>
<translation>Bekapcsolás ideje</translation>
</message>
@@ -1668,10 +1888,6 @@
<translation>Blokklánc</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Aktuális blokkok száma</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memória Halom</translation>
</message>
@@ -1716,10 +1932,6 @@
<translation>Peer kijelölése a részletes információkért</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Engedélyezett</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Irány</translation>
</message>
@@ -1740,6 +1952,14 @@
<translation>Szinkronizált Blokkok</translation>
</message>
<message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation>A megadott "Önálló rendszer" használom a peer választás diverzifikálásához.</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation>Felvett AS (önálló rendszer)</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation>User Agent</translation>
</message>
@@ -1748,6 +1968,10 @@
<translation>Csomópont ablak</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Jelenlegi legmagasabb blokkszám</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>A %1 debug log fájl megnyitása a jelenlegi könyvtárból. Ez néhány másodpercig eltarthat nagyobb log fájlok esetén.</translation>
</message>
@@ -1760,12 +1984,12 @@
<translation>Betűméret növelése</translation>
</message>
<message>
- <source>Services</source>
- <translation>Szolgáltatások</translation>
+ <source>Permissions</source>
+ <translation>Jogosultságok</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Kazenske točke</translation>
+ <source>Services</source>
+ <translation>Szolgáltatások</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1916,14 +2140,6 @@
<translation>Kimenő</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Igen</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nem</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Ismeretlen</translation>
</message>
@@ -1959,6 +2175,14 @@
<translation>Egy opcionálisan kérhető összeg. Hagyja üresen, vagy írjon be nullát, ha nem kívánja használni.</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>Egy opcionális címke, amit hozzá lehet rendelni az új fogadó címhez (amit használhatsz a számla azonosításához). E mellett hozzá lesz csatolva a fizetési kérelemhez is.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Egy opcionális üzenet ami a fizetési kérelemhez van fűzve és valószínűleg meg lesz jelenítve a fizető oldalán.</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
<translation>&amp;Új fogadócím létrehozása</translation>
</message>
@@ -2014,56 +2238,60 @@
<source>Copy amount</source>
<translation>Összeg másolása</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Nem sikerült a tárca megnyitása</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Cím generálása sikertelen %1 </translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR kód</translation>
+ <source>Request payment to ...</source>
+ <translation>Fizetési igény ...-nek</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>&amp;URI másolása</translation>
+ <source>Address:</source>
+ <translation>Cím:</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Cím másolása</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Kép mentése</translation>
+ <source>Amount:</source>
+ <translation>Összeg:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Fizetés kérése a %1 -hez</translation>
+ <source>Label:</source>
+ <translation>Címke:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Fizetési információ</translation>
+ <source>Message:</source>
+ <translation>Üzenet:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Tárca:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Cím</translation>
+ <source>Copy &amp;URI</source>
+ <translation>&amp;URI másolása</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Összeg</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Cím másolása</translation>
</message>
<message>
- <source>Label</source>
- <translation>Címke</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Kép mentése</translation>
</message>
<message>
- <source>Message</source>
- <translation>Üzenet</translation>
+ <source>Request payment to %1</source>
+ <translation>Fizetés kérése a %1 -hez</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Tárca</translation>
+ <source>Payment information</source>
+ <translation>Fizetési információ</translation>
</message>
</context>
<context>
@@ -2168,6 +2396,14 @@
<translation>Figyelem: A hozzávetőleges díjszámítás jelenleg nem lehetséges.</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 of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>Add meg a választott tranzakciós díjat kB (1000 bájt) -onként a tranzakció virtuális méretére számolva.
+
+Figyelem: Mivel bájtonként lesz a dj kiszámolva ezért a "100 satoshi per kB" egy 500 bájtos (fél kB) tranzakciónál ténylegesen 50 satoshi lesz.</translation>
+ </message>
+ <message>
<source>per kilobyte</source>
<translation>kilobájtonként</translation>
</message>
@@ -2208,6 +2444,10 @@
<translation>Rejtsd el a tranzakciós költségek beállításait</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>Ha kevesebb a tranzakció mint amennyi hely lenne egy blokkban, akkor a bányászok és a többi node megkövetelheti a minimum díjat. E minimum díjat fizetni elegendő lehet, de tudnod kell, hogy ez esetleg soha nem konfirmálódó tranzakciót eredményezhet ahogy a tranzakciók száma magasabb lesz mint a network által megengedett.</translation>
+ </message>
+ <message>
<source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
<translation>A túl alacsony illeték a tranzakció soha be nem teljesülését eredményezheti (olvassa el az elemleírást)</translation>
</message>
@@ -2220,6 +2460,10 @@
<translation>Replace-By-Fee bekapcsolása</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>A With Replace-By-Fee (BIP-125) funkciót használva küldés után is megemelheted a tranzakciós díjat. Ha ezt nem használod akkor magasabb díjat érdemes használni, hogy kisebb legyen a késedelem.</translation>
+ </message>
+ <message>
<source>Clear &amp;All</source>
<translation>Mindent &amp;töröl</translation>
</message>
@@ -2268,18 +2512,50 @@
<translation>%1 (%2 blokov)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>&amp;Aláírás nélkül létrehozása Unsigned</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>Létrehoz egy Részlegesen Aláírt Bitcoin Tranzakciót (PSBT) melyet offline %1 tárcával vagy egy PSBT kompatibilis hardver tárcával használhatsz.</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>A "%1" tárcától</translation>
</message>
<message>
+ <source>%1 to '%2'</source>
+ <translation>%1 -től '%2-ig'</translation>
+ </message>
+ <message>
<source>%1 to %2</source>
<translation>%1 do %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Piszkozatba teszed ezt a tranzakciót?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<translation>Biztosan el akarja küldeni?</translation>
</message>
<message>
+ <source>Create Unsigned</source>
+ <translation>Aláíratlan létrehozása</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Tranzakció adatainak mentése</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Részlegesen Aláírt Tranzakció (PSBT bináris) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PBST elmentve</translation>
+ </message>
+ <message>
<source>or</source>
<translation>vagy</translation>
</message>
@@ -2288,6 +2564,10 @@
<translation>Később növelheti a tranzakció díját (lásd 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>
+ <translation>Kérlek nézd át a tranzakciós javaslatot. Ez létrehoz egy Részlegesen Aláírt Bitcoin Tranzakciót (PSBT) amit elmenthetsz vagy kimásolhatsz. Aztán aláírhatod: offline %1 tárcával vagy egy PSBT kompatibilis hardver tárcával.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Kérjük, hogy ellenőrizze le a tranzakcióját.</translation>
</message>
@@ -2296,6 +2576,10 @@
<translation>Tranzakciós díj</translation>
</message>
<message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Nem jelzek Replace-By-Fee, BIP-125-t</translation>
+ </message>
+ <message>
<source>Total Amount</source>
<translation>Teljes összeg</translation>
</message>
@@ -2308,10 +2592,18 @@
<translation>Összeg küldésének megerősítése</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <translation>Tranzakció javaslat megerősítése</translation>
+ </message>
+ <message>
<source>Send</source>
<translation>Küldés</translation>
</message>
<message>
+ <source>Watch-only balance:</source>
+ <translation>Egyenleg csak megfigyelésre</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>A fogadó címe érvénytelen. Kérem ellenőrizze.</translation>
</message>
@@ -2343,6 +2635,10 @@
<source>Payment request expired.</source>
<translation>A fizetési kérelem lejárt.</translation>
</message>
+ <message numerus="yes">
+ <source>Estimated to begin confirmation within %n block(s).</source>
+ <translation><numerusform>Becsülhetőn %n blokkon belül kerül be.</numerusform><numerusform>Estimated to begin confirmation within %n blocks.</numerusform></translation>
+ </message>
<message>
<source>Warning: Invalid Bitcoin address</source>
<translation>Figyelmeztetés: Érvénytelen Bitcoin cím</translation>
@@ -2403,6 +2699,10 @@
<translation>Ez a bejegyzés eltávolítása</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>A küldendő összeg a választott egységben.</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>Znesek plačila bo zmanjšan za znesek provizije. Prejemnik bo prejel manjše število kovancev, kot je bil vnešeni znesek. Če je prejemnikov več, bo provizija med njih enakomerno porazdeljena.</translation>
</message>
@@ -2529,6 +2829,14 @@
<translation>Bitcoin cím, amivel aláírta az üzenetet</translation>
</message>
<message>
+ <source>The signed message to verify</source>
+ <translation>Az aláírt üzenet ellenőrzésre</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>A kapott aláírás amikor az üzenet alá lett írva.</translation>
+ </message>
+ <message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
<translation>Ellenőrizze az üzenetet, hogy valóban a megjelölt Bitcoin címmel van-e aláírva</translation>
</message>
@@ -2606,6 +2914,10 @@
</context>
<context>
<name>TransactionDesc</name>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>%n további blokkra megnyitva</numerusform><numerusform>%n további blokkra megnyitva</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>%1 -ig megnyitva</translation>
@@ -2682,6 +2994,10 @@
<source>Credit</source>
<translation>Jóváírás</translation>
</message>
+ <message numerus="yes">
+ <source>matures in %n more block(s)</source>
+ <translation><numerusform>beérik %n blokk múlva</numerusform><numerusform>beérik %n blokk múlva</numerusform></translation>
+ </message>
<message>
<source>not accepted</source>
<translation>elutasítva</translation>
@@ -2792,6 +3108,10 @@
<source>Label</source>
<translation>Címke</translation>
</message>
+ <message numerus="yes">
+ <source>Open for %n more block(s)</source>
+ <translation><numerusform>%n további blokkra megnyitva</numerusform><numerusform>%n további blokkra megnyitva</numerusform></translation>
+ </message>
<message>
<source>Open until %1</source>
<translation>%1 -ig megnyitva</translation>
@@ -3061,12 +3381,28 @@
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>A tárca hosszantartó bezárása nyesési üzemmódban azt eredményezheti, hogy a teljes láncot újra kell szinkronizálnia.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Összes tárca bezárása</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Biztos, hogy be akarod zárni az összes tárcát?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nincs betöltve pénztárca.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Nincs tárca megnyitva.
+A Fájl &gt; Megnyitás menüben lehet megnyitni.
+- VAGY -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Új tárca készítése</translation>
</message>
</context>
<context>
@@ -3076,6 +3412,10 @@
<translation>Érmék Küldése</translation>
</message>
<message>
+ <source>Fee bump error</source>
+ <translation>Díj emelési hiba</translation>
+ </message>
+ <message>
<source>Increasing transaction fee failed</source>
<translation>Tranzakciós díj növelése sikertelen</translation>
</message>
@@ -3084,6 +3424,10 @@
<translation>Kívánja megnövelni a díjat?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Akarsz egy piszkozat tranzakciót díj emeléssel?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>Jelenlegi díj:</translation>
</message>
@@ -3096,6 +3440,18 @@
<translation>Új díj:</translation>
</message>
<message>
+ <source>Confirm fee bump</source>
+ <translation>Erősitsd meg a díj emelését</translation>
+ </message>
+ <message>
+ <source>Can't draft transaction.</source>
+ <translation>Sikertelen tranzakciós piszkozat</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT másolva</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>Tranzakció aláírása sikertelen.</translation>
</message>
@@ -3119,6 +3475,30 @@
<translation>Jelenlegi nézet adatainak exportálása fájlba</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Hiba</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>PSBT sikertelen dekódolása a vágólapról (base64 érvénytelen)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Tranzakció adatainak betöltése</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Részlegesen Aláírt Tranzakció (PSBT bináris) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>A PSBT fájlnak kisebbnek kell lennie mint 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>PSBT dekódolása sikertelen</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Biztonsági másolat készítése a Tárcáról</translation>
</message>
@@ -3162,10 +3542,6 @@
<translation>Nyesés: az utolsó tárcaszinkronizálás meghaladja a nyesett adatokat. Szükséges a -reindex használata (nyesett csomópont esetében a teljes blokklánc ismételt letöltése).</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Hiba: Fatális belső hiba történt, nézze meg a debug.log -ot a részletekért</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Obrezujem ...</translation>
</message>
@@ -3182,14 +3558,34 @@
<translation>Az %s adatkönyvtár nem zárható. A %s valószínűleg fut már.</translation>
</message>
<message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Nem lehetséges a megadott kapcsolatok és az addrman által felderített kapcsolatok egyidejű használata.</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>Hiba %s beolvasása közben. Az összes kulcs sikeresen beolvasva, de a tranzakciós adatok és a címtár rekordok hiányoznak vagy sérültek.</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>Opozorilo: Preverite, če sta datum in ura na vašem računalniku točna! %s ne bo deloval pravilno, če je nastavljeni čas nepravilen.</translation>
</message>
<message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Kérlek támogasd ha hasznásnak találtad a %s-t. Az alábbi linken találsz bővebb információt a szoftverről %s.</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>A blokk adatbázis tartalmaz egy blokkot ami a jövőből érkezettnek látszik. Ennek oka lehet, hogy a számítógéped dátum és idő beállítása helytelen. Csak akkor építsd újra a block adatbázist ha biztos vagy benne, hogy az időbeállítás helyes.</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>Ez egy kiadás előtt álló, teszt verzió - csak saját felelősségre - ne használja bányászatra vagy kereskedéshez.</translation>
</message>
<message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>Ezt a tranzakciós díjat figyelmen kívül hagyhatod ha a visszajáró kisebb mint a "porhintés" összege jelenleg.</translation>
+ </message>
+ <message>
<source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
<translation>Ne morem ponoviti blokov. Podatkovno bazo bo potrebno ponovno zgraditi z uporabo ukaza -reindex-chainstate.</translation>
</message>
@@ -3206,14 +3602,6 @@
<translation>Opozorilo: Trenutno se s soležniki ne strinjamo v popolnosti! Mogoče bi morali vi ali drugi udeleženci posodobiti odjemalce.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d od zadnjih 100 blokov imajo nepričakovano verzijo</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s poškodovana, obnova neuspešna</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool legalább %d MB kell legyen.</translation>
</message>
@@ -3226,6 +3614,10 @@
<translation>Indeks drobiža izven dovoljenega območja</translation>
</message>
<message>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation>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>
+ <message>
<source>Copyright (C) %i-%i</source>
<translation>Szerzői jog (C) fenntartva %i-%i</translation>
</message>
@@ -3234,6 +3626,14 @@
<translation>Sérült blokk-adatbázis észlelve</translation>
</message>
<message>
+ <source>Could not find asmap file %s</source>
+ <translation>%s asmap fájl nem található</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>%s beolvasása sikertelen</translation>
+ </message>
+ <message>
<source>Do you want to rebuild the block database now?</source>
<translation>Újra akarod építeni a blokk adatbázist most?</translation>
</message>
@@ -3250,6 +3650,10 @@
<translation>Hiba a(z) %s betöltése közben</translation>
</message>
<message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation> %s betöltése sikertelen. A privát kulcsok csak a létrehozáskor tilthatóak le.</translation>
+ </message>
+ <message>
<source>Error loading %s: Wallet corrupted</source>
<translation>Hiba a(z) %s betöltése közben: A tárca hibás.</translation>
</message>
@@ -3282,6 +3686,10 @@
<translation>Helytelen vagy nemlétező genézis blokk. Helytelen hálózati adatkönyvtár?</translation>
</message>
<message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>%s bezárása folyamatban. A kezdeti hibátlansági teszt sikertelen.</translation>
+ </message>
+ <message>
<source>Invalid P2P permission: '%s'</source>
<translation>Érvénytelen P2P jog: '%s'</translation>
</message>
@@ -3298,16 +3706,24 @@
<translation>Neveljavna količina za -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>A megadott blokk "%s" nem létezik.</translation>
+ </message>
+ <message>
<source>Unknown address type '%s'</source>
<translation>Ismeretlen cím típus '%s'</translation>
</message>
<message>
- <source>Loading P2P addresses...</source>
- <translation>P2P címek betöltése...</translation>
+ <source>Unknown change type '%s'</source>
+ <translation>Visszajáró típusa ismeretlen '%s'</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Hiba: A lemezen kevés hely elérhető!</translation>
+ <source>Upgrading txindex database</source>
+ <translation>txindex adatbázis frissítése</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>P2P címek betöltése...</translation>
</message>
<message>
<source>Loading banlist...</source>
@@ -3346,10 +3762,22 @@
<translation>Na tem računalniku ni bilo mogoče vezati naslova %s. %s je verjetno že zagnan.</translation>
</message>
<message>
+ <source>Unable to generate keys</source>
+ <translation>Kulcs generálás sikertelen</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Nem támogatott logolási kategória %s=%s</translation>
+ </message>
+ <message>
<source>Upgrading UTXO database</source>
<translation>Blokk adatbázis frissítése</translation>
</message>
<message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation>Az ügyfélügynök megjegyzésben nem biztonságos karakter van: (%s) </translation>
+ </message>
+ <message>
<source>Verifying blocks...</source>
<translation>Blokkok ellenőrzése...</translation>
</message>
@@ -3362,10 +3790,50 @@
<translation>Napaka: Ni mogoče sprejemati dohodnih povezav (vrnjena napaka: %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s sérült. Megpróbálhatod a bitcoint-wallet tárcaj mentő eszközt, vagy mentésből helyreállítani a tárcát.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>A korábbi (nem HD) tárca nem frissíthető. Először frissíteni kell, hogy támogassa a "pre split keypool"-t. Használd a 169900 verziót vagy olyat amiben egyáltalán nincs verzió megadva.</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>Érvénytelen összeg -maxtxfee=&lt;amount&gt;: '%s' (legalább a minrelay összeg azaz %s kell legyen, hogy ne ragadjon be a tranzakció)</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation>A tranzakció összege túl alacsony az elküldéshez miután a díj levonódik</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>Ez a hiba akkor jelentkezhet ha a tárca nem volt rendesen lezárva és egy újabb verziójában volt megnyitva a Berkeley DB-nek. Ha így van akkor használd azt a verziót amivel legutóbb megnyitottad.</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>Ez a maximum tranzakciós díj amit fizetni fogsz (a normál díj felett), hogy prioritizáld a részleges költés elkerülést a normál coin választás felett.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>A tranzakcióhoz szükség van egy visszajáró címre de nem tudtam létrehozni. Kérem először töltsd újra a címtárat a keypoolrefill paranccsal.</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>Újra kell építeni az adatbázist a -reindex használatával, ami a nyesett üzemmódot megszünteti. Ez a teljes blokklánc ismételt letöltésével jár.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Súlyos belső hiba történt, részletek a debug.log-ban</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>-peerblockfilters csak a -blockfilterindex -vel együtt állítható be.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Kevés a hely a lemezen!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Hiba az adatbázis olvasásakor, leállítás</translation>
</message>
@@ -3374,10 +3842,42 @@
<translation>Hiba a blokk adatbázis betöltése közben</translation>
</message>
<message>
+ <source>Error: Disk space is low for %s</source>
+ <translation>Hiba: kevés a hely a lemezen %s -nek!</translation>
+ </message>
+ <message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>A címraktár kiürült, tötsd újra a keyppolrefill paranccsal.</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>A választott díj (%s) alacsonyabb mint a beállított minimum díj (%s)</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Érvénytelen -onion cím vagy hostname: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Érvénytelen -proxy cím vagy hostname: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
+ <translation>Érvénytelen tranzakciós díj -paytxfee=&lt;amount&gt;: '%s' (minimum ennyinek kell legyen %s)</translation>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation>Érvénytelen hálózati maszk van megadva itt: -whitelist: '%s'</translation>
+ </message>
+ <message>
<source>Need to specify a port with -whitebind: '%s'</source>
<translation>Pri opciji -whitebind morate navesti vrata: %s</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>Proxy szerver nincs megadva. A megadás módja: -proxy=&lt;ip&gt; vagy -proxy=&lt;ip:port&gt;</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>A -blockfilterindex nem használható nyesés üzemmódban.</translation>
</message>
@@ -3386,6 +3886,10 @@
<translation>Zmanjšujem maksimalno število povezav (-maxconnections) iz %d na %d, zaradi sistemskih omejitev.</translation>
</message>
<message>
+ <source>Section [%s] is not recognized.</source>
+ <translation>Ismeretlen szekció [%s]</translation>
+ </message>
+ <message>
<source>Signing transaction failed</source>
<translation>Tranzakció aláírása sikertelen</translation>
</message>
@@ -3402,6 +3906,16 @@
<translation>A megadott "%s" -walletdir nem könyvtár</translation>
</message>
<message>
+ <source>The specified config file %s does not exist
+</source>
+ <translation>A megadott konfigurációs fájl %s nem található.
+</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>A tranzakció összege túl alacsony a tranzakciós költség kifizetéséhez.</translation>
+ </message>
+ <message>
<source>This is experimental software.</source>
<translation>Ez egy kísérleti szoftver.</translation>
</message>
@@ -3418,10 +3932,18 @@
<translation>Na tem računalniku ni bilo mogoče vezati naslova %s (vrnjena napaka: %s)</translation>
</message>
<message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation>PID fájl létrehozása sikertelen '%s': %s</translation>
+ </message>
+ <message>
<source>Unable to generate initial keys</source>
<translation>Ne zmorem ustvariti začetnih ključev</translation>
</message>
<message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Ismeretlen -blockfilterindex érték %s.</translation>
+ </message>
+ <message>
<source>Verifying wallet(s)...</source>
<translation>Tárcák ellenőrzése...</translation>
</message>
@@ -3430,12 +3952,16 @@
<translation>Opozorilo: neznana nova pravila aktivirana (verzija %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>A tárca összes trancakciójának törlése...</translation>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation>-maxtxfee túl magasra van állítva! Ez a jelentős díj esetleg már egy egyszeri tranzakcióra is ki lehet fizetve.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Figyelem: A tárca-fájl megsérült, de az adatokat sikerült megmenteni! Az eredeti %s fájlt mentettük %s név alatt a %s könyvtárban. Amennyiben az egyenleg vagy a trancakciók helytelenek, állítsa vissza tárcáját a biztonsági mentés használatával.</translation>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>Ezt a tranzakciós díjat fogod fizetni ha a díjbecslés nem lehetséges.</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation>A hálózati verzió string (%i) hossza túllépi a megengedettet (%i). Csökkentsd a hosszt vagy a darabszámot uacomments beállításban.</translation>
</message>
<message>
<source>%s is set very high!</source>
@@ -3466,6 +3992,10 @@
<translation>Tranzakció összege nem lehet negatív</translation>
</message>
<message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>A tranzakcóihoz tartozó mempool elődlánc túl hosszú</translation>
+ </message>
+ <message>
<source>Transaction must have at least one recipient</source>
<translation>Legalább egy címzett kell a tranzakcióhoz</translation>
</message>
@@ -3478,14 +4008,18 @@
<translation>Fedezethiány</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>A nem HD-s megosztott tárcát nem lehet bővíteni anélkül, hogy először a megosztás előtti kulcskészlet támogatására bővít. Használja az -upgradewallet=169900 parancsot vagy az -upgradewallet parancsot verzió megadása nélkül.</translation>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Díjbecslés sikertelen. Alapértelmezett díj le van tiltva. Fárj néhány blokkot vagy engedélyezd a -fallbackfee -t.</translation>
</message>
<message>
<source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
<translation>Figyelem: Privát kulcsokat észleltünk a {%s} tárcában, melynél a privát kulcsok le vannak tiltva.</translation>
</message>
<message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Nem tudok írni a '%s' könyvtárba, ellenőrizd a jogosultságokat.</translation>
+ </message>
+ <message>
<source>Loading block index...</source>
<translation>Blokkindex betöltése...</translation>
</message>
diff --git a/src/qt/locale/bitcoin_id.ts b/src/qt/locale/bitcoin_id.ts
index 09d3b87bca..51aafc98b8 100644
--- a/src/qt/locale/bitcoin_id.ts
+++ b/src/qt/locale/bitcoin_id.ts
@@ -70,10 +70,6 @@
<translation>Berikut ialah alamat-alamat Bitcoin Anda yang digunakan untuk mengirimkan pembayaran. Selalu periksa jumlah dan alamat penerima sebelum mengirimkan koin.</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.</source>
- <translation>Ini adalah alamat Bitcoin untuk menerima pembayaran. Gunakan tombol 'Buat alamat penerima baru' di tab terima untuk membuat alamat baru.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Salin Alamat</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Dompet saat ini &lt;b&gt;terenkripsi&lt;/b&gt; dan &lt;b&gt;terkunci&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Terjadi Kesalahan Fatal. Bitcoin Tidak Dapat Melanjutkan Dengan Aman Dan Akan Keluar</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1139,10 +1131,6 @@
<translation>Perlihatkan apabila proxy SOCKS5 default digunakan untuk berhungan dengan orang lain lewat tipe jaringan ini.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Menggunakan proxy SOCKS5 tersendiri untuk berhubungan dengan orang lain melalui layanan Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Sembunyikan ikon dari system tray.</translation>
</message>
@@ -1275,10 +1263,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Koneksi ke jaringan bitcoin melalui proxy SOCKS5 yang berbeda untuk layanan Tor tersembunyi.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Jendela</translation>
</message>
@@ -1453,7 +1437,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>Jumlah saldo di alamat hanya lihat</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Jumlah Keseluruhan</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>atau</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1712,6 @@
<translation>Rantai blok</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Jumlah blok terkini</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1765,10 +1756,6 @@
<translation>Pilih satu peer untuk melihat informasi detail.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelist</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Panduan</translation>
</message>
@@ -1789,6 +1776,14 @@
<translation>Block Yang Telah Sinkron</translation>
</message>
<message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation>Sistem Otonom yang dipetakan digunakan untuk mendiversifikasi pilihan peer</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation>AS yang Dipetakan</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation>Agen Pengguna
@@ -1815,10 +1810,6 @@
<translation>Layanan</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban Score</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Waktu Koneksi</translation>
</message>
@@ -1963,14 +1954,6 @@
<translation>keluar</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ya</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Tidak</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Tidak diketahui</translation>
</message>
@@ -2010,6 +1993,10 @@
<translation>Label fakultatif untuk menghubungkan dengan alamat penerima baru (anda menggunakannya untuk mengindetifikasi faktur). Itu juga dilampirkan pada permintaan pembayaran.</translation>
</message>
<message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>Pesan opsional yang dilampirkan di permintaan pembayaran dan dapat ditampilkan ke pengirim.</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
<translation>&amp;Create alamat penerima baru</translation>
</message>
@@ -2065,12 +2052,24 @@
<source>Copy amount</source>
<translation>Salin Jumlah</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Tidak dapat membuka dompet.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Kode QR</translation>
+ <source>Amount:</source>
+ <translation>Nilai:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Pesan:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Wallet:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2092,30 +2091,6 @@
<source>Payment information</source>
<translation>Informasi pembayaran</translation>
</message>
- <message>
- <source>URI</source>
- <translation>Tautan</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Alamat</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Jumlah</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Pesan</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Dompet</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2391,18 +2366,10 @@ Catatan: Karena biaya dihitung berdasarkan per byte, biaya "100 satoshi per kB"
<translation>Konfirmasi proposal transaksi</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Salin PSBT ke papan klip</translation>
- </message>
- <message>
<source>Send</source>
<translation>Kirim</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT disalin</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Saldo (hanya lihat):</translation>
</message>
@@ -3148,12 +3115,12 @@ Catatan: Karena biaya dihitung berdasarkan per byte, biaya "100 satoshi per kB"
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Menutup dompet terlalu lama dapat menyebabkan harus menyinkron ulang seluruh rantai jika pemangkasan diaktifkan.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Tidak ada dompent yang dimuat.</translation>
+ <source>Create a new wallet</source>
+ <translation>Bikin dompet baru</translation>
</message>
</context>
<context>
@@ -3226,6 +3193,10 @@ Catatan: Karena biaya dihitung berdasarkan per byte, biaya "100 satoshi per kB"
<translation>Ekspor data dalam tab sekarang ke sebuah berkas</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Kesalahan</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Cadangkan Dompet</translation>
</message>
@@ -3269,10 +3240,6 @@ Catatan: Karena biaya dihitung berdasarkan per byte, biaya "100 satoshi per kB"
<translation>Pemangkasan: sinkronisasi dompet terakhir melampaui data yang sudah dipangkas. Anda perlu -reindex (unduh seluruh blockchain lagi jika terjadi node pemangkasan)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: Kesalahan internal fatal terjadi, lihat debug.log untuk detailnya</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Memangkas blockstore...</translation>
</message>
@@ -3353,10 +3320,6 @@ Catatan: Karena biaya dihitung berdasarkan per byte, biaya "100 satoshi per kB"
<translation>Memuat alamat P2P....</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Eror: Kapasitas penyimpanan penuh!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Memuat banlist...</translation>
</message>
@@ -3483,10 +3446,6 @@ Catatan: Karena biaya dihitung berdasarkan per byte, biaya "100 satoshi per kB"
<translation>Memverifikasi dompet...</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Setiap transaksi dalam dompet sedang di-'Zap'...</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s diset sangat tinggi!</translation>
</message>
diff --git a/src/qt/locale/bitcoin_is.ts b/src/qt/locale/bitcoin_is.ts
index 25fe30bbdd..61e9078e1e 100644
--- a/src/qt/locale/bitcoin_is.ts
+++ b/src/qt/locale/bitcoin_is.ts
@@ -495,11 +495,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Veskið er &lt;b&gt;dulkóðað&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Alvarleg villa átti sér stað. Bitcoin getur ekki haldið áfram með öruggum hætti og stoppar hér.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -695,7 +691,10 @@
<source>Current total balance in watch-only addresses</source>
<translation>Innistæða á færslugildum sem eru einungis til skoðunar</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -727,10 +726,6 @@
<translation>Blokkarkeðja</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Núverandi fjöldi blokka</translation>
- </message>
- <message>
<source>Starting Block</source>
<translation>Upphafsblokk</translation>
</message>
@@ -761,22 +756,10 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>Vistfang</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Upphæð</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Merki</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Veski</translation>
+ <source>Amount:</source>
+ <translation>Upphæð:</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -925,6 +908,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Flytja gögn í flipanum í skrá</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Villa</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_it.ts b/src/qt/locale/bitcoin_it.ts
index a8137d3031..80131e5b42 100644
--- a/src/qt/locale/bitcoin_it.ts
+++ b/src/qt/locale/bitcoin_it.ts
@@ -3,7 +3,7 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>Fai clic con il tasto destro del mouse per modificare l'indirizzo o l'etichetta</translation>
+ <translation>Fai clic con il tasto destro del mouse per modificare l'indirizzo oppure l'etichetta</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>Copia negli appunti l'indirizzo attualmente selezionato</translation>
+ <translation>Copia negli appunti del sistema l'indirizzo attualmente selezionato</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -70,8 +70,10 @@
<translation>Questi sono i tuoi indirizzi Bitcoin per l'invio di pagamenti. Controlla sempre l'importo e l'indirizzo del beneficiario prima di inviare 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.</source>
- <translation>Questi sono i tuoi indirizzi Bitcoin per ricevere pagamenti. Usa il tasto "Crea nuovo indirizzo ricevente" nella schermata "Ricevi" per creare nuovi indirizzi.</translation>
+ <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>Questi sono i tuoi indirizzi Bitcoin per ricevere pagamenti. Usa il tasto "Crea nuovo indirizzo ricevente" nella schermata "Ricevi" per creare nuovi indirizzi.
+E' possibile firmare solo con indirizzi di tipo "legacy".</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -87,11 +89,11 @@
</message>
<message>
<source>Export Address List</source>
- <translation>Esporta elenco indirizzi</translation>
+ <translation>Esporta elenco degli indirizzi</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Testo CSV (*.csv)</translation>
+ <translation>File diviso da virgole (*.csv)</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -169,7 +171,7 @@
</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>Attenzione: Se si cifra il portamonete e si perde la passphrase &lt;b&gt;TUTTI I PROPRI BITCOIN ANDRANNO PERSI&lt;/b&gt;!</translation>
+ <translation>Attenzione: Se si cifra il portafoglio e si perde la passphrase &lt;b&gt;TUTTI I PROPRI BITCOIN ANDRANNO PERSI&lt;/b&gt;!</translation>
</message>
<message>
<source>Are you sure you wish to encrypt your wallet?</source>
@@ -482,6 +484,22 @@
<translation>Aggiornato</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Carica PSBT da file...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Carica Partially Signed Bitcoin Transaction</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Carica PSBT dagli appunti...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Carica Partially Signed Bitcoin Transaction dagli appunti</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Finestra del nodo</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Chiudi il portafoglio</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Chiudi Tutti i Portafogli...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Chiudi tutti i portafogli</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Mostra il messaggio di aiuto di %1 per ottenere una lista di opzioni di comando per Bitcoin</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Valori della maschera</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Maschera i valori nella sezione "Panoramica"</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>Portafoglio predefinito:</translation>
</message>
@@ -630,8 +664,12 @@
<translation>Il portamonete è &lt;b&gt;cifrato&lt;/b&gt; ed attualmente &lt;b&gt;bloccato&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Si è verificato un errore critico. Bitcoin non può più funzionare in maniera sicura e verrà chiuso.</translation>
+ <source>Original message:</source>
+ <translation>Messaggio originale:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Si è verificato un errore critico. %1 non può più continuare in maniera sicura e verrà chiuso.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Crea Portafoglio Vuoto</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Usa descriptors per gestione scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Descrizione del Portafoglio</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Crea</translation>
</message>
@@ -1139,10 +1185,6 @@
<translation>Mostra se il proxy SOCK5 di default che p stato fornito è usato per raggiungere i contatti attraverso questo tipo di rete.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Usa una SOCKS&amp;5 proxy differente per raggiungere peers usando servizi Tor hidden</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Nascondi l'icona nella barra delle applicazioni.</translation>
</message>
@@ -1276,10 +1318,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Connette alla rete Bitcoin attraverso un proxy SOCKS5 separato per Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Finestra</translation>
</message>
@@ -1320,6 +1358,14 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Specifica se le funzionalita di coin control saranno visualizzate.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Connette alla rete Bitcoin attraverso un proxy SOCKS5 separato per i Tor onion services.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Usa un proxy SOCKS&amp;5 separato per raggiungere peers attraverso i Tor onion services.</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;URL di terze parti per transazioni</translation>
</message>
@@ -1454,6 +1500,133 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<source>Current total balance in watch-only addresses</source>
<translation>Saldo corrente totale negli indirizzi di sola lettura</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Modalità privacy attivata per la scheda "Panoramica". Per smascherare i valori, deseleziona Impostazioni-&gt; Valori maschera.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialogo</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Firma Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Trasmetti Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Copia negli Appunti</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Salva...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Chiudi</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Caricamento della transazione fallito: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Firma della transazione fallita: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Non posso firmare piu' inputs.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Firmato %1 inputs, ma sono richieste piu' firme.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Transazione firmata con successo. La transazione é pronta per essere trasmessa.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Errore sconosciuto processando la transazione.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Transazione trasmessa con successo! ID della transazione: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Trasmissione della transazione fallita: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT copiata negli appunti.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Salva Dati Transazione</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transazione Parzialmente Firmata (Binario) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT salvata su disco.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation> * Invia %1 a %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Non in grado di calcolare la fee della transazione o l'ammontare totale della transazione.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Paga fee della transazione: </translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Importo totale</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>o</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>La transazione ha %1 inputs non firmati.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>La transazione manca di alcune informazioni sugli inputs.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>La transazione necessita ancora di firma/e.</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Ma questo portafoglio non può firmare transazioni.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Ma questo portafoglio non ha le chiavi giuste.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>La transazione è completamente firmata e pronta per essere trasmessa.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Lo stato della transazione è sconosciuto.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1620,6 +1793,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Errore: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Errore durante l'inizializzazione delle impostazioni: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 non è ancora stato chiuso in modo sicuro</translation>
</message>
@@ -1718,10 +1895,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Numero attuale di blocchi</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1766,10 +1939,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Seleziona un peer per visualizzare informazioni più dettagliate.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted/sicuri</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direzione</translation>
</message>
@@ -1806,6 +1975,10 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Finestra del nodo</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Altezza del blocco corrente</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>Apri il file log del debug di %1 dalla cartella dati attuale. Può richiedere alcuni secondi per file di log di grandi dimensioni.</translation>
</message>
@@ -1818,12 +1991,12 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>Aumenta dimensioni font</translation>
</message>
<message>
- <source>Services</source>
- <translation>Servizi</translation>
+ <source>Permissions</source>
+ <translation>Permessi</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Punteggio di Ban</translation>
+ <source>Services</source>
+ <translation>Servizi</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1974,14 +2147,6 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<translation>In uscita</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Si</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Sconosciuto</translation>
</message>
@@ -2080,56 +2245,60 @@ Per specificare più URL separarli con una barra verticale "|".</translation>
<source>Copy amount</source>
<translation>Copia l'importo</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Impossibile sbloccare il portafoglio.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Non è stato possibile generare il nuovo %1 indirizzo</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Codice QR</translation>
+ <source>Request payment to ...</source>
+ <translation>Richiedi pagamento a ...</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>Copia &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Copia &amp;Indirizzo</translation>
+ <source>Address:</source>
+ <translation>Indirizzo:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Salva Immagine...</translation>
+ <source>Amount:</source>
+ <translation>Importo:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Richiesta di pagamento a %1</translation>
+ <source>Label:</source>
+ <translation>Etichetta:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Informazioni di pagamento</translation>
+ <source>Message:</source>
+ <translation>Messaggio:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Portafoglio:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Indirizzo</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copia &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Importo</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Copia &amp;Indirizzo</translation>
</message>
<message>
- <source>Label</source>
- <translation>Etichetta</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Salva Immagine...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Messaggio</translation>
+ <source>Request payment to %1</source>
+ <translation>Richiesta di pagamento a %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Portafoglio</translation>
+ <source>Payment information</source>
+ <translation>Informazioni di pagamento</translation>
</message>
</context>
<context>
@@ -2378,8 +2547,20 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Sei sicuro di voler inviare?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Per favore, rivedi la tua proposta di transazione. Questo produrrà una Transazione Bitcoin Parzialmente Firmata (PSBT) che puoi copiare e quindi firmare con es. un portafoglio %1 offline o un portafoglio hardware compatibile con PSBT.</translation>
+ <source>Create Unsigned</source>
+ <translation>Crea non Firmata</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Salva Dati Transazione</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transazione Parzialmente Firmata (Binario) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT salvata</translation>
</message>
<message>
<source>or</source>
@@ -2390,6 +2571,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Si puó aumentare la commissione successivamente (segnalando 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>
+ <translation>Per favore, controlla la tua proposta di transazione. Questo produrrà una Partially Signed Bitcoin Transaction (PSBT) che puoi salvare o copiare e quindi firmare con es. un portafoglio %1 offline o un portafoglio hardware compatibile con PSBT.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Per favore, rivedi la tua transazione.</translation>
</message>
@@ -2418,18 +2603,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Conferma la proposta di transazione</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copia PSBT negli appunti</translation>
- </message>
- <message>
<source>Send</source>
<translation>Invia</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copiata</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Saldo watch-only</translation>
</message>
@@ -3211,12 +3388,28 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Chiudere il portafoglio per troppo tempo può causare la resincronizzazione dell'intera catena se la modalità "pruning" è attiva.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Chiudi tutti i portafogli</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Sei sicuro di voler chiudere tutti i portafogli?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Non è stato caricato alcun portafoglio.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Nessun portafoglio è stato caricato.
+Vai su File &gt; Apri Portafoglio per caricare un portafoglio.
+- OR -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Crea un nuovo portafoglio</translation>
</message>
</context>
<context>
@@ -3289,6 +3482,30 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Esporta su file i dati contenuti nella tabella corrente</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Errore</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Non in grado di decodificare PSBT dagli appunti (base64 non valida)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Carica Dati Transazione</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Transazione Parzialmente Firmata (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>Il file PSBT deve essere inferiore a 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Non in grado di decodificare PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup Portafoglio</translation>
</message>
@@ -3332,10 +3549,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Prune: l'ultima sincronizzazione del portafoglio risulta essere precedente alla eliminazione dei dati per via della modalità "pruning". È necessario eseguire un -reindex (scaricare nuovamente la blockchain in caso di nodo pruned).</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Errore: si è presentato un errore interno fatale, consulta il file debug.log per maggiori dettagli</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning del blockstore...</translation>
</message>
@@ -3348,10 +3561,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Sviluppatori di %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Impossibile generare una chiave per il resto. Non c'è nessuna chiave nel keypool interno ed è impossibile generare altre chiavi.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Non è possibile ottenere i dati sulla cartella %s. Probabilmente %s è già in esecuzione.</translation>
</message>
@@ -3364,6 +3573,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Errore lettura %s! Tutte le chiavi sono state lette correttamente, ma i dati delle transazioni o della rubrica potrebbero essere mancanti o non corretti.</translation>
</message>
<message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation>Viene fornito più di un indirizzo di associazione onion. L'utilizzo di %s per il servizio Tor onion viene creato automaticamente.</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>Per favore controllate che la data del computer e l'ora siano corrette! Se il vostro orologio è sbagliato %s non funzionerà correttamente.</translation>
</message>
@@ -3400,14 +3613,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Attenzione: Sembra che non vi sia pieno consenso con i nostri peer! Un aggiornamento da parte tua o degli altri nodi potrebbe essere necessario.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d degli ultimi 100 blocchi hanno una versione inaspettata</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrotto, recupero fallito</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool deve essere almeno %d MB</translation>
</message>
@@ -3484,6 +3689,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Impossibile ripetere la scansione del portafoglio durante l'inizializzazione</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Errore nella verifica del database</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importazione...</translation>
</message>
@@ -3512,6 +3721,22 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Importo non valido per -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Errore nell'eseguire l'operazione di verifica del database: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Errore nel verificare il database: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase: Errore nella lettura della verifica del database: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase: Application id non riconosciuto. Mi aspetto un %u, arriva un %u</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>La cartella specificata "%s" non esiste.</translation>
</message>
@@ -3532,10 +3757,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Caricamento indirizzi P2P...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Errore: Spazio su disco insufficiente!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Caricamento bloccati...</translation>
</message>
@@ -3600,6 +3821,14 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Errore: attesa per connessioni in arrivo fallita (errore riportato %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s corrotto. Prova a usare la funzione del portafoglio bitcoin-wallet per salvare o recuperare il backup</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Impossibile aggiornare un portafoglio diviso non HD senza aggiornamento per supportare il keypool pre-split. Si prega di utilizzare -upgradewallet = 169900 o -upgradewallet senza specificare la versione.</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>Importo non valido per -maxtxfee=&lt;amount&gt;: '%s' (deve essere almeno pari alla commissione 'minrelay fee' di %s per prevenire transazioni bloccate)</translation>
</message>
@@ -3608,10 +3837,30 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>L'importo della transazione risulta troppo basso per l'invio una volta dedotte le commissioni.</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>Questo errore potrebbe essersi verificato se questo portafoglio non è stato chiuso in modo pulito ed è stato caricato l'ultima volta utilizzando una build con una versione più recente di Berkeley DB. In tal caso, utilizza il software che ha caricato per ultimo questo portafoglio</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>La transazione richiede un indirizzo di resto, ma non possiamo generarlo. Si prega di eseguire prima keypoolrefill.</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>Per ritornare alla modalità unpruned sarà necessario ricostruire il database utilizzando l'opzione -reindex. L'intera blockchain sarà riscaricata.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Si è verificato un errore interno fatale, consultare debug.log per i dettagli</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Non e' possibile impostare -peerblockfilters senza -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Lo spazio su disco è insufficiente!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Errore durante la lettura del database. Arresto in corso.</translation>
</message>
@@ -3624,6 +3873,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Errore: lo spazio sul disco è troppo poco per %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Errore: Keypool esaurito, esegui prima keypoolrefill</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Indirizzo -onion o hostname non valido: '%s'</translation>
</message>
@@ -3644,6 +3897,10 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>È necessario specificare una porta con -whitebind: '%s'</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>Nessun server proxy specificato. Usa -proxy=&lt;ip&gt; o -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>La modalità ridotta(pruned) non è compatibile con -blockfilterindex</translation>
</message>
@@ -3718,10 +3975,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Attenzione: nuove regole non conosciute attivate (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Eliminazione dal portafoglio di tutte le transazioni...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee è impostato molto alto! Commissioni così alte possono venir pagate anche su una singola transazione.</translation>
</message>
@@ -3734,10 +3987,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>La lunghezza totale della stringa di network version (%i) eccede la lunghezza massima (%i). Ridurre il numero o la dimensione di uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Attenzione: file del Portafoglio corrotto, dati recuperati! %s originale salvato come %s in %s; se il saldo o le transazioni non sono corrette effettua un ripristino da un backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s ha un'impostazione molto alta!</translation>
</message>
@@ -3782,10 +4031,6 @@ Nota: poiché la commissione è calcolata su base per byte, una commissione di "
<translation>Fondi insufficienti</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Impossibile aggiornare un portafoglio diviso non HD senza aggiornamento per supportare il keypool pre-split. Si prega di utilizzare -upgradewallet = 169900 o -upgradewallet senza specificare la versione.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Stima della commissione non riuscita. Fallbackfee è disabilitato. Attendi qualche blocco o abilita -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ja.ts b/src/qt/locale/bitcoin_ja.ts
index e40e5ec4fb..ccbc135c16 100644
--- a/src/qt/locale/bitcoin_ja.ts
+++ b/src/qt/locale/bitcoin_ja.ts
@@ -70,10 +70,6 @@
<translation>これらは、あなたが知っている送信先の 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.</source>
- <translation>これらは支払いを受け取るための、あなたの Bitcoin アドレスです。新しいアドレスを作成するには受取タブ内の「新しい受取用アドレスを作成」ボタンを使用します。</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>アドレスをコピー(&amp;C)</translation>
</message>
@@ -483,6 +479,14 @@
<translation>ブロックは最新</translation>
</message>
<message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>PSBTをクリップボードから読み込み</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>部分的に署名されたビットコインのトランザクションをクリップボードから読み込み</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>ノードウィンドウ</translation>
</message>
@@ -519,6 +523,14 @@
<translation>ウォレットを閉じる</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>全てのウォレットを閉じる</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>全てのウォレットを閉じる</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>%1 のヘルプ メッセージを表示し、使用可能な Bitcoin のコマンドラインオプション一覧を見る。</translation>
</message>
@@ -631,10 +643,10 @@
<translation>ウォレットは&lt;b&gt;暗号化済み&lt;/b&gt;・&lt;b&gt;ロック状態&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>致命的なエラーが発生しました。Bitcoin を安全に動作し続けることができないため終了します。</translation>
+ <source>Original message:</source>
+ <translation>オリジナルメッセージ:</translation>
</message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1140,10 +1152,6 @@
<translation>指定されたデフォルト SOCKS5 プロキシが、このネットワークタイプ経由でピアに接続しているかどうか。</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Tor秘匿サービス経由でピアに接続するために専用の SOCKS5 プロキシを利用する(&amp;5):</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>システムトレイのアイコンを隠す</translation>
</message>
@@ -1276,10 +1284,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Tor秘匿サービスを利用するため、専用の SOCKS5 プロキシ経由で Bitcoin ネットワークに接続する。</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>ウインドウ(&amp;W)</translation>
</message>
@@ -1454,7 +1458,46 @@
<source>Current total balance in watch-only addresses</source>
<translation>ウォッチ限定アドレスの現在の残高の総計</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>ダイアログ</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>クリップボードにコピー</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>保存</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>閉じる</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>トランザクションへの署名が成功しました。トランザクションのブロードキャストの準備ができています。</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>トランザクションデータの保存</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBTはディスクに保存されました。</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>合計</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>または</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1718,10 +1761,6 @@
<translation>ブロック チェーン</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>現在のブロック数</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>メモリ プール</translation>
</message>
@@ -1766,10 +1805,6 @@
<translation>詳しい情報を見たいピアを選択してください。</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>ホワイトリスト登録済み</translation>
- </message>
- <message>
<source>Direction</source>
<translation>方向</translation>
</message>
@@ -1822,10 +1857,6 @@
<translation>サービス</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Banスコア</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>接続時間</translation>
</message>
@@ -1974,14 +2005,6 @@
<translation>外向き</translation>
</message>
<message>
- <source>Yes</source>
- <translation>はい</translation>
- </message>
- <message>
- <source>No</source>
- <translation>いいえ</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>不明</translation>
</message>
@@ -2080,12 +2103,32 @@
<source>Copy amount</source>
<translation>金額をコピー</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>ウォレットをアンロックできませんでした。</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QRコード</translation>
+ <source>Address:</source>
+ <translation>アドレス:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>金額:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>ラベル:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>メッセージ:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>ウォレット:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2107,30 +2150,6 @@
<source>Payment information</source>
<translation>支払い情報</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>アドレス</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>金額</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>ラベル</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>メッセージ</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>ウォレット</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2378,8 +2397,8 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>送金してもよろしいですか?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>トランザクション提案を確認してください。これにより、部分的に署名されたビットコイン・トランザクション(PSBT)が作成されます。これをコピーして例えばオフラインの %1 ウォレットやPSBTを扱えるハードウェアウォレットで残りの署名が出来ます。</translation>
+ <source>Save Transaction Data</source>
+ <translation>トランザクションデータの保存</translation>
</message>
<message>
<source>or</source>
@@ -2418,18 +2437,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>トランザクション提案を承認する</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>PSBTをクリップボードにコピー</translation>
- </message>
- <message>
<source>Send</source>
<translation>送金</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBTがコピーされました</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>監視限定残高</translation>
</message>
@@ -3211,12 +3222,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>ブロックファイル剪定が有効の場合、長期間ウォレットを起動しないと全チェーンを再度同期させる必要があるかもしれません。</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>全てのウォレットを閉じる</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>本当に全てのウォレットを閉じますか。</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>ウォレットが読み込まれていません。</translation>
+ <source>Create a new wallet</source>
+ <translation>新しいウォレットを作成</translation>
</message>
</context>
<context>
@@ -3289,6 +3308,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>現在のタブのデータをファイルにエクスポート</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>エラー</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>ウォレットのバックアップ</translation>
</message>
@@ -3332,10 +3355,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>剪定: 最後のウォレット同期ポイントが、剪定されたデータを越えています。-reindex を実行する必要があります (剪定されたノードの場合、ブロックチェーン全体を再ダウンロードします)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>エラー: 致命的な内部エラーが発生しました。詳細は debug.log を参照してください</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>ブロック保存容量を剪定中...</translation>
</message>
@@ -3348,10 +3367,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%s の開発者</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>おつりアドレスの鍵を作成することができません。内部のキープールに鍵が存在しないため、鍵を生成することができません。</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>データ ディレクトリ %s のロックを取得することができません。%s がおそらく既に実行中です。</translation>
</message>
@@ -3400,14 +3415,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>警告: ピアと完全に合意が取れていないようです! このノードもしくは他のノードのアップグレードが必要な可能性があります。</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>直近の100ブロックの内、%d ブロックが予期しないバージョンを含んでいます</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s が壊れています。復旧にも失敗しました</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempoolは最低でも %d MB必要です</translation>
</message>
@@ -3532,10 +3539,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>P2Pアドレスの読み込み中...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>エラー: ディスク容量が不足しています!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>banリストの読み込み中...</translation>
</message>
@@ -3612,6 +3615,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>非剪定モードに戻るためには -reindex オプションを指定してデータベースを再構築する必要があります。 ブロックチェーン全体の再ダウンロードが必要となります。</translation>
</message>
<message>
+ <source>Disk space is too low!</source>
+ <translation>ディスク容量不足!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>データベースの読み込みエラー。シャットダウンします。</translation>
</message>
@@ -3718,10 +3725,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>警告: 未知の新しいルールが有効化されました (バージョンビット %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>ウォレットから全取引を消去中...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee が非常に高く設定されています! ひとつの取引でこの金額の手数料が支払われてしまうことがあります。</translation>
</message>
@@ -3734,10 +3737,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>ネットワークバージョン文字列の長さ(%i)が、最大の長さ(%i) を超えています。UAコメントの数や長さを削減してください。</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>警告: ウォレットファイルが破損していたため、データを復旧しました! 復旧前の %s は %s として %s に保存されました。残高や取引が正しくない場合にはバックアップから復元してください。</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s の設定値が高すぎです!</translation>
</message>
@@ -3782,10 +3781,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>残高不足</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>分割済みキープールをサポートするようにアップグレードしないと、非HD分割ウォレットをアップグレードすることはできません。 -upgradewallet=169900 オプションか、バージョン指定無しで -upgradewallet オプションを指定してください。</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>手数料推定に失敗しました。代替手数料が無効です。数ブロック待つか、-fallbackfee オプションを有効にしてください。</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ka.ts b/src/qt/locale/bitcoin_ka.ts
index 5d230d28c4..3581ba3c59 100644
--- a/src/qt/locale/bitcoin_ka.ts
+++ b/src/qt/locale/bitcoin_ka.ts
@@ -481,11 +481,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>საფულე &lt;b&gt;დაშიფრულია&lt;/b&gt; და ამჟამად &lt;b&gt;დაბლოკილია&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>ფატალური შეცდომა. Bitcoin ვერ უზრუნველყოფს უსაფრთხო გაგრძელებას, ამიტომ იხურება.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -967,6 +963,13 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>ან</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1105,10 +1108,6 @@
<translation>ბლოკთა ჯაჭვი</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>ბლოკების მიმდინარე რაოდენობა</translation>
- </message>
- <message>
<source>Last block time</source>
<translation>ბოლო ბლოკის დრო</translation>
</message>
@@ -1215,12 +1214,24 @@
<source>Copy amount</source>
<translation>რაოდენობის კოპირება</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>საფულის განბლოკვა ვერ მოხერხდა.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-კოდი</translation>
+ <source>Amount:</source>
+ <translation>თანხა:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>მესიჯი:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>საფულე:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1242,30 +1253,6 @@
<source>Payment information</source>
<translation>ინფორმაცია გადახდის შესახებ</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>მისამართი</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>თანხა</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>ნიშნული</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>მესიჯი</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>საფულე</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2001,11 +1988,7 @@
</context>
<context>
<name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>არ არის ჩატვირთული საფულე.</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletModel</name>
<message>
@@ -2028,6 +2011,10 @@
<translation>ამ ბარათიდან მონაცემების ექსპორტი ფაილში</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>შეცდომა</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>საფულის არქივირება</translation>
</message>
@@ -2119,10 +2106,6 @@
<translation>ტრანსაქცია ძალიან დიდია</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>ტრანსაქციების ჩახსნა საფულიდან...</translation>
- </message>
- <message>
<source>Unknown network specified in -onlynet: '%s'</source>
<translation>-onlynet-ში მითითებულია უცნობი ქსელი: '%s'</translation>
</message>
diff --git a/src/qt/locale/bitcoin_kk.ts b/src/qt/locale/bitcoin_kk.ts
index 9ca9b48149..5b56827b9a 100644
--- a/src/qt/locale/bitcoin_kk.ts
+++ b/src/qt/locale/bitcoin_kk.ts
@@ -199,6 +199,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -235,14 +238,10 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Amount</source>
+ <source>Amount:</source>
<translation>Саны</translation>
</message>
- <message>
- <source>Wallet</source>
- <translation>Әмиян</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -335,6 +334,10 @@
<source>&amp;Export</source>
<translation>Экспорт</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>қате</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_km.ts b/src/qt/locale/bitcoin_km.ts
index 4ef5205777..20ce9814f8 100644
--- a/src/qt/locale/bitcoin_km.ts
+++ b/src/qt/locale/bitcoin_km.ts
@@ -3,11 +3,11 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>ចុចម៉ៅស្ដាំ ដើម្បីកែសម្រួលអាសយដ្ឋាន រឺស្លាក</translation>
+ <translation>ចុចម៉ៅស្តាំ ដើម្បីកែសម្រួលអាសយដ្ឋាន រឺស្លាក</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>បង្កើតអាសយដ្ឋានថ្មីមួយ</translation>
+ <translation>បង្កើតអាស្រយដ្ឋានថ្មីមួយ</translation>
</message>
<message>
<source>&amp;New</source>
@@ -31,7 +31,7 @@
</message>
<message>
<source>Enter address or label to search</source>
- <translation>វាយអាសយដ្ឋាន រឺស្លាកដើម្បីស្វែងរក</translation>
+ <translation>វាយអាសយដ្ឋាន រឺ បិទស្លាក ដើម្បីស្វែងរក</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -70,10 +70,6 @@
<translation>ទាំងនេះ​គឺជាអាសយដ្ឋាន 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.</source>
- <translation>ទាំងនេះ​គឺជាអាសយដ្ឋាន Bitcoin របស់អ្នកសម្រាប់ធ្វើការទទួលបង់ប្រាក់។ ប្រើប៊ូតុង "បង្កើតអាសយដ្ឋានទទួលថ្មី" ស្ថិតក្នុងផ្ទាំងទទួល ដើម្បីបង្កើតអាសយដ្ឋានថ្មីមួយ។</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>ចម្លងអាសយដ្ឋាន</translation>
</message>
@@ -463,6 +459,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -483,18 +482,10 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>អាសយដ្ឋាន</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>ឡាបែល</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>កាបូប</translation>
+ <source>Wallet:</source>
+ <translation>កាបូបចល័ត៖</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -569,7 +560,11 @@
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>បង្កើតកាបូបចល័តថ្មី</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
</context>
@@ -583,6 +578,10 @@
<source>Export the data in the current tab to a file</source>
<translation>នាំចេញទិន្នន័យនៃថេបបច្ចុប្បន្នទៅជាឯកសារ</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>បញ្ហា</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_ko.ts b/src/qt/locale/bitcoin_ko.ts
index b79d53a74a..00944be3ef 100644
--- a/src/qt/locale/bitcoin_ko.ts
+++ b/src/qt/locale/bitcoin_ko.ts
@@ -70,10 +70,6 @@
<translation>비트코인을 보내는 계좌 주소입니다. 코인을 보내기 전에 금액과 받는 주소를 항상 확인하세요.</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.</source>
- <translation>지불 수신용 비트코인주소. 신규 주소를 만들려면 'Create new receiving address' 버튼을 사용하세요.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>주소 복사(&amp;C)</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>지갑이 &lt;b&gt;암호화&lt;/b&gt; 되었고 현재 &lt;b&gt;잠겨져&lt;/b&gt; 있습니다</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>치명적인 오류가 발생했습니다. 비트코인을 더이상 안전하게 진행할 수 없어 곧 종료합니다.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1119,10 +1111,6 @@
<translation>제공된 기본 SOCKS5 프록시가 이 네트워크 유형을 통해 피어에 도달하는 경우 표시됩니다.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Tor 서비스를 이용하여 피어에게 연결하기 위해 분리된 SOCKS5 프록시 사용:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>시스템 트레이 로 부터 아이콘 숨기기</translation>
</message>
@@ -1255,10 +1243,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Tor 서비스를 경유하여 비트코인 네트워크에 연결하기 위해 분리된 SOCKS5 프록시를 사용합니다.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>창(&amp;W)</translation>
</message>
@@ -1433,7 +1417,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>조회전용 주소의 현재 잔액</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>총액</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>또는</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1697,10 +1692,6 @@
<translation>블록 체인</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>현재 블록 수</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>메모리 풀</translation>
</message>
@@ -1745,10 +1736,6 @@
<translation>자세한 정보를 보려면 피어를 선택하세요.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>화이트리스트에 포함</translation>
- </message>
- <message>
<source>Direction</source>
<translation>방향</translation>
</message>
@@ -1793,10 +1780,6 @@
<translation>서비스</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>밴 스코어</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>접속 시간</translation>
</message>
@@ -1945,14 +1928,6 @@
<translation>아웃바운드</translation>
</message>
<message>
- <source>Yes</source>
- <translation>예</translation>
- </message>
- <message>
- <source>No</source>
- <translation>아니오</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>알수없음</translation>
</message>
@@ -2043,12 +2018,24 @@
<source>Copy amount</source>
<translation>거래액 복사</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>지갑을 잠금해제 할 수 없습니다.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR 코드</translation>
+ <source>Amount:</source>
+ <translation>거래액:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>메시지:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>지갑:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2070,30 +2057,6 @@
<source>Payment information</source>
<translation>지불 정보</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>주소</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>거래액</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>라벨</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>메시지</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>지갑</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2361,18 +2324,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>코인 전송을 확인</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>PSBT를 클립보드에 복사</translation>
- </message>
- <message>
<source>Send</source>
<translation>보내기</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT 복사됨</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>조회전용 잔액:</translation>
</message>
@@ -3142,12 +3097,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>블록축소를 하고 지갑을 너무 오랫동안 닫으면 체인 전체를 다시 동기화해야 할 수도 있습니다.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>지갑 불러오기가 안됩니다.</translation>
+ <source>Create a new wallet</source>
+ <translation>새로운 지갑 생성하기</translation>
</message>
</context>
<context>
@@ -3212,6 +3167,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>현재 탭에 있는 데이터를 파일로 내보내기</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>오류</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>지갑 백업</translation>
</message>
@@ -3255,10 +3214,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>블록 축소: 마지막 지갑 동기화 지점이 축소된 데이터보다 과거의 것 입니다. -reindex가 필요합니다 (축소된 노드의 경우 모든 블록체인을 재다운로드합니다)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>오류: 치명적인 내부 오류가 발생했습니다, 자세한 내용은 debug.log 를 확인해주세요.</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>블록 데이터를 축소 중입니다..</translation>
</message>
@@ -3271,10 +3226,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%s 개발자</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>거스름돈 주소 생성 불가. 내장 지갑 열쇠 보관함에 열쇠가 없으면 새로운 열쇠를 생성할 수 없습니다.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>%s 데이터 디렉토리에 락을 걸 수 없었습니다. %s가 이미 실행 중인 것으로 보입니다.</translation>
</message>
@@ -3323,14 +3274,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>경고: 현재 비트코인 버전이 다른 네트워크 참여자들과 동일하지 않은 것 같습니다. 당신 또는 다른 참여자들이 동일한 비트코인 버전으로 업그레이드 할 필요가 있습니다.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>지난 100개의 블록 중 %d개에 예상치 못한 버전이 있습니다.</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s 손상되었고 복구가 실패하였습니다</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool은 최소한 %d MB 이어야 합니다</translation>
</message>
@@ -3451,10 +3394,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>P2P 주소 불러오는 중...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>오류: 디스크 공간이 부족합니다!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>추방리스트를 불러오는 중...</translation>
</message>
@@ -3637,10 +3576,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>경고: 알려지지 않은 새로운 규칙이 활성화되었습니다. (버전비트 %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>지갑의 모든거래내역 건너뛰기...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee 값이 너무 큽니다! 하나의 거래에 너무 큰 수수료가 지불 됩니다.</translation>
</message>
@@ -3653,10 +3588,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>네트워크 버전 문자 (%i)의 길이가 최대길이 (%i)를 초과합니다. uacomments의 갯수나 길이를 줄이세요.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>경고 : 지갑파일이 손상되어 데이터가 복구되었습니다. 원래의 %s 파일은 %s 후에 %s 이름으로 저장됩니다. 잔액과 거래 내역이 정확하지 않다면 백업 파일로 부터 복원해야 합니다.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s가 매우 높게 설정되었습니다!</translation>
</message>
@@ -3701,10 +3632,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>잔액이 부족합니다</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>HD split을 하지 않은 지갑은 pre split keypool로 업그레이드 하지 않은 이상 업그레이드가 불가능합니다. -upgradewallet=169900 이나 -upgradewallet (버전을 정하지 않고) 명령을 사용하십시오.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>수수료 추정이 실패했습니다. Fallbackfee가 비활성화 상태입니다. 몇 블록을 기다리거나 -fallbackfee를 활성화 하세요.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ku_IQ.ts b/src/qt/locale/bitcoin_ku_IQ.ts
index 68ddf09ddc..8552770aea 100644
--- a/src/qt/locale/bitcoin_ku_IQ.ts
+++ b/src/qt/locale/bitcoin_ku_IQ.ts
@@ -171,6 +171,13 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>یان</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -256,14 +263,6 @@
<source>never</source>
<translation>هەرگیز</translation>
</message>
- <message>
- <source>Yes</source>
- <translation>بەڵێ</translation>
- </message>
- <message>
- <source>No</source>
- <translation>نەخێر</translation>
- </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -291,16 +290,12 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>ناوونیشان</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>سەرجەم</translation>
+ <source>Amount:</source>
+ <translation>کۆ:</translation>
</message>
<message>
- <source>Message</source>
- <translation>پەیام</translation>
+ <source>Message:</source>
+ <translation>پەیام:</translation>
</message>
</context>
<context>
@@ -447,6 +442,10 @@
<source>&amp;Export</source>
<translation>&amp;هەناردن</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>هەڵە</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_ky.ts b/src/qt/locale/bitcoin_ky.ts
index bfb9c663fd..04fabae0e4 100644
--- a/src/qt/locale/bitcoin_ky.ts
+++ b/src/qt/locale/bitcoin_ky.ts
@@ -163,6 +163,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -215,18 +218,10 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>Дарек</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Билдирүү</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Капчык</translation>
+ <source>Message:</source>
+ <translation>Билдирүү:</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -335,6 +330,10 @@
</context>
<context>
<name>WalletView</name>
+ <message>
+ <source>Error</source>
+ <translation>Ката</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_la.ts b/src/qt/locale/bitcoin_la.ts
index 830a665844..2eaf377d65 100644
--- a/src/qt/locale/bitcoin_la.ts
+++ b/src/qt/locale/bitcoin_la.ts
@@ -341,11 +341,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Cassidile &lt;b&gt;cifratum&lt;/b&gt; est et iam nunc &lt;b&gt;seratum&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Error fatalis accidit. Bitcoin nondum pergere tute potest, et exibit.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -595,6 +591,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Cannot start bitcoin: click-to-pay handler</source>
@@ -669,10 +668,6 @@
<translation>Catena frustorum</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Numerus frustorum iam nunc</translation>
- </message>
- <message>
<source>Last block time</source>
<translation>Hora postremi frusti</translation>
</message>
@@ -715,34 +710,30 @@
<source>Copy amount</source>
<translation>Copia quantitatem</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Copia Inscriptionem</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Inscriptio</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>Non potuisse cassidile reserare</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Amount</source>
- <translation>Quantitas</translation>
+ <source>Amount:</source>
+ <translation>Quantitas:</translation>
</message>
<message>
- <source>Label</source>
- <translation>Titulus</translation>
+ <source>Label:</source>
+ <translation>Titulus:</translation>
</message>
<message>
- <source>Message</source>
- <translation>Nuntius</translation>
+ <source>Message:</source>
+ <translation>Nuntius:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Cassidile</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Copia Inscriptionem</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1320,6 +1311,10 @@
<translation>Exporta data in hac tabella in plicam</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Conserva cassidile</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lt.ts b/src/qt/locale/bitcoin_lt.ts
index 7024bff0a2..1c1fc292bf 100644
--- a/src/qt/locale/bitcoin_lt.ts
+++ b/src/qt/locale/bitcoin_lt.ts
@@ -70,10 +70,6 @@
<translation>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.</source>
- <translation>Tai jūsų Bitcoin mokėjimų gavimo adresai. Naudokite 'Sukurti naują gavimo adresą' migtuką gavimų skirtuke kad sukurtumėt nauja adresą.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopijuoti adresą</translation>
</message>
@@ -597,11 +593,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Piniginė &lt;b&gt;užšifruota&lt;/b&gt; ir šiuo metu &lt;b&gt;užrakinta&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Kritinė klaida. Bitcoin nebegali tęsti saugiai ir bus išjungtas.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1079,10 +1071,6 @@
<translation>Rodo, ar pridedamas numatytasis SOCKS5 proxy naudojamas pasiekti Peers per šį tinklo tipą.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Naudokite atskirą SOCKS&amp;5 tarpinius serverius, kad pasiektumėte Peers per „Tor“ paslėptas paslaugas:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Slėpti piktogramą</translation>
</message>
@@ -1215,10 +1203,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Prisijunkite prie „Bitcoin“ tinklo per atskirą „SOCKS5“ proxy „Tor“ paslėptas paslaugas.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Langas</translation>
</message>
@@ -1393,7 +1377,22 @@
<source>Current total balance in watch-only addresses</source>
<translation>Dabartinis visas balansas tik stebimų adresų</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialogas</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Visas kiekis</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ar</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1645,10 +1644,6 @@
<translation>Blokų grandinė</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Dabartinis blokų skaičius</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool</translation>
</message>
@@ -1693,10 +1688,6 @@
<translation>Pasirinkite peer, kad galėtumėte peržiūrėti išsamią informaciją.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Baltasis sąrašas</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Kryptis</translation>
</message>
@@ -1737,10 +1728,6 @@
<translation>Paslaugos</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Uždraudimo balas</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Ryšio laikas</translation>
</message>
@@ -1889,14 +1876,6 @@
<translation>Išsiunčiamas</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Taip</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ne</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Nežinomas</translation>
</message>
@@ -1983,12 +1962,28 @@
<source>Copy amount</source>
<translation>Kopijuoti sumą</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Nepavyko atrakinti piniginės.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR kodas</translation>
+ <source>Amount:</source>
+ <translation>Suma:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Žymė:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Žinutė:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Piniginė</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2010,30 +2005,6 @@
<source>Payment information</source>
<translation>Mokėjimo informacija</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresas</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Suma</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Žymė</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Žinutė</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Piniginė</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -3014,8 +2985,8 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Piniginė nebuvo įkelta.</translation>
+ <source>Create a new wallet</source>
+ <translation>Sukurti naują piniginę</translation>
</message>
</context>
<context>
@@ -3076,6 +3047,10 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>Eksportuokite duomenis iš dabartinio skirtuko į failą</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Klaida</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Sukurti Piniginės atsarginę kopiją</translation>
</message>
@@ -3111,14 +3086,6 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>%s kūrėjai</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d iš paskutinių 100 blokų turi nenumatyą versiją</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s sugadintas, išgelbėjimas nepavyko</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool turi būti bent %d MB</translation>
</message>
@@ -3195,10 +3162,6 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>Užkraunami P2P adresai...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Klaida: Diske mažai vietos!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Įkeliamas draudžiamas sąrašas...</translation>
</message>
@@ -3251,10 +3214,6 @@ Pastaba: Kadangi mokestis apskaičiuojamas pagal baitą, mokestis už „100 sat
<translation>Tikrinama piniginė(s)...</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Visų operacijų sulaikymas iš piniginės...</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s labai aukštas!</translation>
</message>
diff --git a/src/qt/locale/bitcoin_lv.ts b/src/qt/locale/bitcoin_lv.ts
index 360b2735c0..5ac13296e8 100644
--- a/src/qt/locale/bitcoin_lv.ts
+++ b/src/qt/locale/bitcoin_lv.ts
@@ -116,6 +116,10 @@
<translation>Jaunā parole vēlreiz</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Rādīt paroli</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Šifrēt maciņu</translation>
</message>
@@ -128,6 +132,10 @@
<translation>Atšifrēt maciņu</translation>
</message>
<message>
+ <source>Change passphrase</source>
+ <translation>Mainīt paroli</translation>
+ </message>
+ <message>
<source>Confirm wallet encryption</source>
<translation>Apstiprināt maciņa šifrēšanu</translation>
</message>
@@ -136,6 +144,14 @@
<translation>Vai tu tiešām vēlies šifrēt savu maciņu?</translation>
</message>
<message>
+ <source>Wallet encrypted</source>
+ <translation>Maciņš šifrēts</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Maciņš tagad šifrēts</translation>
+ </message>
+ <message>
<source>Wallet encryption failed</source>
<translation>Maciņa šifrēšana neizdevās</translation>
</message>
@@ -206,6 +222,10 @@
<translation>Atvērt &amp;URI...</translation>
</message>
<message>
+ <source>Wallet:</source>
+ <translation>Maciņš:</translation>
+ </message>
+ <message>
<source>Reindexing blocks on disk...</source>
<translation>Bloku reindeksēšana no diska...</translation>
</message>
@@ -659,6 +679,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -753,10 +776,6 @@
<translation>Bloku virkne</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Pašreizējais bloku skaits</translation>
- </message>
- <message>
<source>Last block time</source>
<translation>Pēdējā bloka laiks</translation>
</message>
@@ -839,8 +858,16 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Kods</translation>
+ <source>Amount:</source>
+ <translation>Daudzums:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Ziņojums:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Maciņš:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -854,23 +881,7 @@
<source>&amp;Save Image...</source>
<translation>&amp;Saglabāt Attēlu...</translation>
</message>
- <message>
- <source>Address</source>
- <translation>Adrese</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Daudzums</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Nosaukums</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Maciņš</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1195,6 +1206,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Datus no tekošā ieliktņa eksportēt uz failu</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Kļūda</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_mk.ts b/src/qt/locale/bitcoin_mk.ts
index 72aea8582f..1c430b486b 100644
--- a/src/qt/locale/bitcoin_mk.ts
+++ b/src/qt/locale/bitcoin_mk.ts
@@ -349,6 +349,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -465,8 +468,12 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Код</translation>
+ <source>Amount:</source>
+ <translation>Сума:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Порака:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -480,15 +487,7 @@
<source>&amp;Save Image...</source>
<translation>&amp;Сними Слика...</translation>
</message>
- <message>
- <source>Amount</source>
- <translation>Сума</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Паричник</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -597,6 +596,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Експортирај ги податоците од активното јазиче во датотека</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Грешка</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_ml.ts b/src/qt/locale/bitcoin_ml.ts
index 2bb3380659..86e9a55d33 100644
--- a/src/qt/locale/bitcoin_ml.ts
+++ b/src/qt/locale/bitcoin_ml.ts
@@ -67,10 +67,6 @@
<translation>പേയ്മെന്റുകൾ അയയ്ക്കുന്നതിനുള്ള നിങ്ങളുടെ ബിറ്റ്കോയിൻ വിലാസങ്ങളാണ് ഇവ. നാണയങ്ങൾ അയയ്ക്കുന്നതിനുമുമ്പ് എല്ലായ്പ്പോഴും തുകയും സ്വീകരിക്കുന്ന വിലാസവും പരിശോധിക്കുക.</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.</source>
- <translation>ഇവയാണ് പണം സ്വീകരിയ്ക്കുന്നതിനായുള്ള താങ്കളുടെ വിലാസങ്ങൾ. പുതിയ വിലാസങ്ങൾ കൂട്ടിച്ചേർക്കുന്നതിനായി ' പുതിയ വിലാസം സൃഷ്ടിയ്ക്കുക ' എന്ന ബട്ടൺ അമർത്തുക.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;വിലാസം പകർത്തുക</translation>
</message>
@@ -418,6 +414,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -446,16 +445,8 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>വിലാസം</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>തുക </translation>
- </message>
- <message>
- <source>Label</source>
- <translation>ലേബൽ</translation>
+ <source>Amount:</source>
+ <translation>തുക:</translation>
</message>
</context>
<context>
@@ -598,6 +589,10 @@
<source>Export the data in the current tab to a file</source>
<translation>നിലവിലെ ടാബിൽ ഒരു ഫയലിൽ ഡാറ്റ എക്സ്പോർട്ട് ചെയ്യുക</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>പിശക് </translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_mn.ts b/src/qt/locale/bitcoin_mn.ts
index 0423c35a68..dabfb97f3b 100644
--- a/src/qt/locale/bitcoin_mn.ts
+++ b/src/qt/locale/bitcoin_mn.ts
@@ -439,6 +439,13 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>эсвэл</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -501,10 +508,6 @@
<translation>Блокийн цуваа</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Одоогийн блокийн тоо</translation>
- </message>
- <message>
<source>Last block time</source>
<translation>Сүүлийн блокийн хугацаа</translation>
</message>
@@ -559,34 +562,26 @@
<source>Copy amount</source>
<translation>Хэмжээг санах</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
- <message>
- <source>Copy &amp;Address</source>
- <translation>Хаягийг &amp;Хуулбарлах</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Хаяг</translation>
- </message>
<message>
- <source>Amount</source>
- <translation>Хэмжээ</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>Түрүйвчийн цоожийг тайлж чадсангүй</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Label</source>
- <translation>Шошго</translation>
+ <source>Amount:</source>
+ <translation>Хэмжээ:</translation>
</message>
<message>
- <source>Message</source>
- <translation>Зурвас</translation>
+ <source>Message:</source>
+ <translation>Зурвас:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Түрүйвч</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Хаягийг &amp;Хуулбарлах</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -993,11 +988,7 @@
</context>
<context>
<name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>Ямар ч түрүйвч ачааллагдсангүй.</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletModel</name>
<message>
@@ -1015,6 +1006,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Сонгогдсон таб дээрхи дата-г экспортлох</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Алдаа</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_mr_IN.ts b/src/qt/locale/bitcoin_mr_IN.ts
index 05e85ec96c..22eef2605c 100644
--- a/src/qt/locale/bitcoin_mr_IN.ts
+++ b/src/qt/locale/bitcoin_mr_IN.ts
@@ -70,10 +70,6 @@
<translation>पैसे पाठविण्यासाठीचे हे तुमचे बिटकॉईन पत्त्ते आहेत. नाणी पाठविण्यापूर्वी नेहमी रक्कम आणि प्राप्त होणारा पत्ता तपासून पहा.</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.</source>
- <translation>पैसे प्राप्त करण्यासाठीचे हे आपले बिटकॉइन पत्ते आहेत. नवीन पत्ते तयार करण्यासाठी प्राप्त टॅबमधील 'नवीन प्राप्त करण्याचा पत्ता तयार करा' बटण वापरा.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;पत्ता कॉपी करा</translation>
</message>
@@ -159,6 +155,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -178,14 +177,6 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>पत्ता</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>लेबल</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_ms.ts b/src/qt/locale/bitcoin_ms.ts
index f5f5bb7a87..4d51ebba02 100644
--- a/src/qt/locale/bitcoin_ms.ts
+++ b/src/qt/locale/bitcoin_ms.ts
@@ -134,6 +134,10 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Ulangi frasa laluan baru</translation>
</message>
<message>
+ <source>Show passphrase</source>
+ <translation>Show passphrase</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>Dompet encrypt</translation>
</message>
@@ -174,6 +178,30 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Dompet dienkripsi</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>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;.</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>Enter the old passphrase and new passphrase for the 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>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</translation>
+ </message>
+ <message>
+ <source>Wallet to be encrypted</source>
+ <translation>Wallet to be encrypted</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Your wallet is about to be encrypted. </translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Your wallet is now encrypted. </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>PENTING: Apa-apa sandaran yang anda buat sebelum ini untuk fail dompet anda hendaklah digantikan dengan fail dompet enkripsi yang dijana baru. Untuk sebab-sebab keselamatan , sandaran fail dompet yang belum dibuat enkripsi sebelum ini akan menjadi tidak berguna secepat anda mula guna dompet enkripsi baru.</translation>
</message>
@@ -296,6 +324,14 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Buka &amp;URI...</translation>
</message>
<message>
+ <source>Create Wallet...</source>
+ <translation>Create Wallet...</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Create a new wallet</translation>
+ </message>
+ <message>
<source>Wallet:</source>
<translation>dompet</translation>
</message>
@@ -320,6 +356,10 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Reindexi blok pada cakera...</translation>
</message>
<message>
+ <source>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</source>
+ <translation>Proxy is &lt;b&gt;enabled&lt;/b&gt;: %1</translation>
+ </message>
+ <message>
<source>Send coins to a Bitcoin address</source>
<translation>Menghantar koin kepada alamat Bitcoin</translation>
</message>
@@ -391,6 +431,34 @@ Alihkan fail data ke dalam tab semasa</translation>
</translation>
</message>
<message>
+ <source>Show the list of used receiving addresses and labels</source>
+ <translation>Show the list of used receiving addresses and labels</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>&amp;Command-line options</translation>
+ </message>
+ <message>
+ <source>Indexing blocks on disk...</source>
+ <translation>Indexing blocks on disk...</translation>
+ </message>
+ <message>
+ <source>Processing blocks on disk...</source>
+ <translation>Processing blocks on disk...</translation>
+ </message>
+ <message>
+ <source>%1 behind</source>
+ <translation>%1 behind</translation>
+ </message>
+ <message>
+ <source>Last received block was generated %1 ago.</source>
+ <translation>Last received block was generated %1 ago.</translation>
+ </message>
+ <message>
+ <source>Transactions after this will not yet be visible.</source>
+ <translation>Transactions after this will not yet be visible.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Ralat</translation>
</message>
@@ -407,10 +475,34 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Terkini</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>Node window</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>Open node debugging and diagnostic console</translation>
+ </message>
+ <message>
+ <source>&amp;Sending addresses</source>
+ <translation>&amp;Sending addresses</translation>
+ </message>
+ <message>
+ <source>&amp;Receiving addresses</source>
+ <translation>&amp;Receiving addresses</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation>Open a bitcoin: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>Buka Wallet</translation>
</message>
<message>
+ <source>Open a wallet</source>
+ <translation>Open a wallet</translation>
+ </message>
+ <message>
<source>Close Wallet...</source>
<translation>Tutup Wallet...</translation>
</message>
@@ -419,28 +511,324 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Tutup Wallet</translation>
</message>
<message>
+ <source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
+ <translation>Show the %1 help message to get a list with possible Bitcoin command-line options</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>dompet lalai
</translation>
</message>
+ <message>
+ <source>No wallets available</source>
+ <translation>No wallets available</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Window</translation>
+ </message>
+ <message>
+ <source>Minimize</source>
+ <translation>Minimize</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation>Zoom</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation>Main Window</translation>
+ </message>
+ <message>
+ <source>%1 client</source>
+ <translation>%1 client</translation>
+ </message>
+ <message>
+ <source>Connecting to peers...</source>
+ <translation>Connecting to peers...</translation>
+ </message>
+ <message>
+ <source>Catching up...</source>
+ <translation>Catching up...</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Error: %1</translation>
+ </message>
+ <message>
+ <source>Warning: %1</source>
+ <translation>Warning: %1</translation>
+ </message>
+ <message>
+ <source>Date: %1
+</source>
+ <translation>Date: %1
+</translation>
+ </message>
+ <message>
+ <source>Amount: %1
+</source>
+ <translation>Amount: %1
+</translation>
+ </message>
+ <message>
+ <source>Wallet: %1
+</source>
+ <translation>Wallet: %1
+</translation>
+ </message>
+ <message>
+ <source>Type: %1
+</source>
+ <translation>Type: %1
+</translation>
+ </message>
+ <message>
+ <source>Label: %1
+</source>
+ <translation>Label: %1
+</translation>
+ </message>
+ <message>
+ <source>Address: %1
+</source>
+ <translation>Address: %1
+</translation>
+ </message>
+ <message>
+ <source>Sent transaction</source>
+ <translation>Sent transaction</translation>
+ </message>
+ <message>
+ <source>Incoming transaction</source>
+ <translation>Incoming transaction</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</source>
+ <translation>HD key generation is &lt;b&gt;enabled&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>HD key generation is &lt;b&gt;disabled&lt;/b&gt;</translation>
+ </message>
+ <message>
+ <source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
+ <translation>Private key &lt;b&gt;disabled&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>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&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>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
+ </message>
</context>
<context>
<name>CoinControlDialog</name>
<message>
+ <source>Coin Selection</source>
+ <translation>Coin Selection</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Quantity:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Amount:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Fee:</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Dust:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>After Fee:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Change:</translation>
+ </message>
+ <message>
+ <source>(un)select all</source>
+ <translation>(un)select all</translation>
+ </message>
+ <message>
+ <source>Tree mode</source>
+ <translation>Tree mode</translation>
+ </message>
+ <message>
+ <source>List mode</source>
+ <translation>List mode</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Amount</translation>
</message>
<message>
+ <source>Received with label</source>
+ <translation>Received with label</translation>
+ </message>
+ <message>
+ <source>Received with address</source>
+ <translation>Received with address</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Date</translation>
+ </message>
+ <message>
+ <source>Confirmations</source>
+ <translation>Confirmations</translation>
+ </message>
+ <message>
+ <source>Confirmed</source>
+ <translation>Confirmed</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copy address</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copy label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copy amount</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copy transaction ID</translation>
+ </message>
+ <message>
+ <source>Lock unspent</source>
+ <translation>Lock unspent</translation>
+ </message>
+ <message>
+ <source>Unlock unspent</source>
+ <translation>Unlock unspent</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Copy quantity</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copy fee</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copy after fee</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copy bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Copy dust</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copy change</translation>
+ </message>
+ <message>
+ <source>(%1 locked)</source>
+ <translation>(%1 locked)</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>yes</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>no</translation>
+ </message>
+ <message>
+ <source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
+ <translation>This label turns red if any recipient receives an amount smaller than the current dust threshold.</translation>
+ </message>
+ <message>
+ <source>Can vary +/- %1 satoshi(s) per input.</source>
+ <translation>Can vary +/- %1 satoshi(s) per input.</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tiada label)</translation>
</message>
- </context>
+ <message>
+ <source>change from %1 (%2)</source>
+ <translation>change from %1 (%2)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(change)</translation>
+ </message>
+</context>
<context>
<name>CreateWalletActivity</name>
- </context>
+ <message>
+ <source>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
+ <translation>Creating Wallet &lt;b&gt;%1&lt;/b&gt;...</translation>
+ </message>
+ <message>
+ <source>Create wallet failed</source>
+ <translation>Create wallet failed</translation>
+ </message>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Create wallet warning</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
- </context>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Create Wallet</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Wallet Name</translation>
+ </message>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Encrypt Wallet</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>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>Disable Private Keys</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>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>Make Blank Wallet</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Create</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
@@ -448,36 +836,244 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Alamat</translation>
</message>
<message>
+ <source>&amp;Label</source>
+ <translation>&amp;Label</translation>
+ </message>
+ <message>
+ <source>The label associated with this address list entry</source>
+ <translation>The label associated with this address list entry</translation>
+ </message>
+ <message>
+ <source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
+ <translation>The address associated with this address list entry. This can only be modified for sending addresses.</translation>
+ </message>
+ <message>
<source>&amp;Address</source>
<translation>Alamat</translation>
</message>
- </context>
+ <message>
+ <source>New sending address</source>
+ <translation>New sending address</translation>
+ </message>
+ <message>
+ <source>Edit receiving address</source>
+ <translation>Edit receiving address</translation>
+ </message>
+ <message>
+ <source>Edit sending address</source>
+ <translation>Edit sending address</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is not a valid Bitcoin address.</source>
+ <translation>The entered address "%1" is not a 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>Address "%1" already exists as a receiving address with label "%2" and so cannot be added as a sending address.</translation>
+ </message>
+ <message>
+ <source>The entered address "%1" is already in the address book with label "%2".</source>
+ <translation>The entered address "%1" is already in the address book with label "%2".</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Could not unlock wallet.</translation>
+ </message>
+ <message>
+ <source>New key generation failed.</source>
+ <translation>New key generation failed.</translation>
+ </message>
+</context>
<context>
<name>FreespaceChecker</name>
- </context>
+ <message>
+ <source>A new data directory will be created.</source>
+ <translation>A new data directory will be created.</translation>
+ </message>
+ <message>
+ <source>name</source>
+ <translation>name</translation>
+ </message>
+ <message>
+ <source>Directory already exists. Add %1 if you intend to create a new directory here.</source>
+ <translation>Directory already exists. Add %1 if you intend to create a new directory here.</translation>
+ </message>
+ <message>
+ <source>Path already exists, and is not a directory.</source>
+ <translation>Path already exists, and is not a directory.</translation>
+ </message>
+ <message>
+ <source>Cannot create data directory here.</source>
+ <translation>Cannot create data directory here.</translation>
+ </message>
+</context>
<context>
<name>HelpMessageDialog</name>
- </context>
+ <message>
+ <source>version</source>
+ <translation>version</translation>
+ </message>
+ <message>
+ <source>About %1</source>
+ <translation>About %1</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Command-line options</translation>
+ </message>
+</context>
<context>
<name>Intro</name>
<message>
+ <source>Welcome</source>
+ <translation>Welcome</translation>
+ </message>
+ <message>
+ <source>Welcome to %1.</source>
+ <translation>Welcome to %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>As this is the first time the program is launched, you can choose where %1 will store its 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>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.</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>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>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>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>Use the default data directory</translation>
+ </message>
+ <message>
+ <source>Use a custom data directory:</source>
+ <translation>Use a custom data directory:</translation>
+ </message>
+ <message>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
+ <source>Discard blocks after verification, except most recent %1 GB (prune)</source>
+ <translation>Discard blocks after verification, except most recent %1 GB (prune)</translation>
+ </message>
+ <message>
+ <source>At least %1 GB of data will be stored in this directory, and it will grow over time.</source>
+ <translation>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>Approximately %1 GB of data will be stored in this directory.</translation>
+ </message>
+ <message>
+ <source>%1 will download and store a copy of the Bitcoin block chain.</source>
+ <translation>%1 will download and store a copy of the Bitcoin block chain.</translation>
+ </message>
+ <message>
+ <source>The wallet will also be stored in this directory.</source>
+ <translation>The wallet will also be stored in this directory.</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" cannot be created.</source>
+ <translation>Error: Specified data directory "%1" cannot be created.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Ralat</translation>
</message>
</context>
<context>
<name>ModalOverlay</name>
- </context>
+ <message>
+ <source>Form</source>
+ <translation>Form</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>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.</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>Attempting to spend bitcoins that are affected by not-yet-displayed transactions will not be accepted by the network.</translation>
+ </message>
+ <message>
+ <source>Number of blocks left</source>
+ <translation>Number of blocks left</translation>
+ </message>
+ <message>
+ <source>Unknown...</source>
+ <translation>Unknown...</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Last block time</translation>
+ </message>
+ <message>
+ <source>Progress</source>
+ <translation>Progress</translation>
+ </message>
+ <message>
+ <source>Progress increase per hour</source>
+ <translation>Progress increase per hour</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>calculating...</translation>
+ </message>
+ <message>
+ <source>Estimated time left until synced</source>
+ <translation>Estimated time left until synced</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Hide</translation>
+ </message>
+ <message>
+ <source>Esc</source>
+ <translation>Esc</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>%1 is currently syncing. It will download headers and blocks from peers and validate them until reaching the tip of the block chain.</translation>
+ </message>
+ <message>
+ <source>Unknown. Syncing Headers (%1, %2%)...</source>
+ <translation>Unknown. Syncing Headers (%1, %2%)...</translation>
+ </message>
+</context>
<context>
<name>OpenURIDialog</name>
- </context>
+ <message>
+ <source>Open bitcoin URI</source>
+ <translation>Open bitcoin URI</translation>
+ </message>
+ <message>
+ <source>URI:</source>
+ <translation>URI:</translation>
+ </message>
+</context>
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation>Open wallet failed</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation>Open wallet warning</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>dompet lalai
</translation>
@@ -490,120 +1086,1971 @@ Alihkan fail data ke dalam tab semasa</translation>
<context>
<name>OptionsDialog</name>
<message>
+ <source>Options</source>
+ <translation>Options</translation>
+ </message>
+ <message>
+ <source>&amp;Main</source>
+ <translation>&amp;Main</translation>
+ </message>
+ <message>
+ <source>Automatically start %1 after logging in to the system.</source>
+ <translation>Automatically start %1 after logging in to the system.</translation>
+ </message>
+ <message>
+ <source>&amp;Start %1 on system login</source>
+ <translation>&amp;Start %1 on system login</translation>
+ </message>
+ <message>
+ <source>Size of &amp;database cache</source>
+ <translation>Size of &amp;database cache</translation>
+ </message>
+ <message>
+ <source>Number of script &amp;verification threads</source>
+ <translation>Number of script &amp;verification threads</translation>
+ </message>
+ <message>
+ <source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
+ <translation>IP address of the proxy (e.g. 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>Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type.</translation>
+ </message>
+ <message>
+ <source>Hide the icon from the system tray.</source>
+ <translation>Hide the icon from the system tray.</translation>
+ </message>
+ <message>
+ <source>&amp;Hide tray icon</source>
+ <translation>&amp;Hide tray icon</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>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.</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>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 |.</translation>
+ </message>
+ <message>
+ <source>Open the %1 configuration file from the working directory.</source>
+ <translation>Open the %1 configuration file from the working directory.</translation>
+ </message>
+ <message>
+ <source>Open Configuration File</source>
+ <translation>Open Configuration File</translation>
+ </message>
+ <message>
+ <source>Reset all client options to default.</source>
+ <translation>Reset all client options to default.</translation>
+ </message>
+ <message>
+ <source>&amp;Reset Options</source>
+ <translation>&amp;Reset Options</translation>
+ </message>
+ <message>
+ <source>&amp;Network</source>
+ <translation>&amp;Network</translation>
+ </message>
+ <message>
+ <source>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</source>
+ <translation>Disables some advanced features but all blocks will still be fully validated. Reverting this setting requires re-downloading the entire blockchain. Actual disk usage may be somewhat higher.</translation>
+ </message>
+ <message>
+ <source>Prune &amp;block storage to</source>
+ <translation>Prune &amp;block storage to</translation>
+ </message>
+ <message>
+ <source>GB</source>
+ <translation>GB</translation>
+ </message>
+ <message>
+ <source>Reverting this setting requires re-downloading the entire blockchain.</source>
+ <translation>Reverting this setting requires re-downloading the entire blockchain.</translation>
+ </message>
+ <message>
+ <source>MiB</source>
+ <translation>MiB</translation>
+ </message>
+ <message>
+ <source>(0 = auto, &lt;0 = leave that many cores free)</source>
+ <translation>(0 = auto, &lt;0 = leave that many cores free)</translation>
+ </message>
+ <message>
+ <source>W&amp;allet</source>
+ <translation>W&amp;allet</translation>
+ </message>
+ <message>
+ <source>Expert</source>
+ <translation>Expert</translation>
+ </message>
+ <message>
+ <source>Enable coin &amp;control features</source>
+ <translation>Enable coin &amp;control features</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>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.</translation>
+ </message>
+ <message>
+ <source>&amp;Spend unconfirmed change</source>
+ <translation>&amp;Spend unconfirmed change</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>Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled.</translation>
+ </message>
+ <message>
+ <source>Map port using &amp;UPnP</source>
+ <translation>Map port using &amp;UPnP</translation>
+ </message>
+ <message>
+ <source>Accept connections from outside.</source>
+ <translation>Accept connections from outside.</translation>
+ </message>
+ <message>
+ <source>Allow incomin&amp;g connections</source>
+ <translation>Allow incomin&amp;g connections</translation>
+ </message>
+ <message>
+ <source>Connect to the Bitcoin network through a SOCKS5 proxy.</source>
+ <translation>Connect to the Bitcoin network through a SOCKS5 proxy.</translation>
+ </message>
+ <message>
+ <source>&amp;Connect through SOCKS5 proxy (default proxy):</source>
+ <translation>&amp;Connect through SOCKS5 proxy (default proxy):</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>Proxy &amp;IP:</translation>
+ </message>
+ <message>
+ <source>&amp;Port:</source>
+ <translation>&amp;Port:</translation>
+ </message>
+ <message>
+ <source>Port of the proxy (e.g. 9050)</source>
+ <translation>Port of the proxy (e.g. 9050)</translation>
+ </message>
+ <message>
+ <source>Used for reaching peers via:</source>
+ <translation>Used for reaching peers via:</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>Tor</source>
+ <translation>Tor</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>&amp;Window</translation>
+ </message>
+ <message>
+ <source>Show only a tray icon after minimizing the window.</source>
+ <translation>Show only a tray icon after minimizing the window.</translation>
+ </message>
+ <message>
+ <source>&amp;Minimize to the tray instead of the taskbar</source>
+ <translation>&amp;Minimize to the tray instead of the taskbar</translation>
+ </message>
+ <message>
+ <source>M&amp;inimize on close</source>
+ <translation>M&amp;inimize on close</translation>
+ </message>
+ <message>
+ <source>&amp;Display</source>
+ <translation>&amp;Display</translation>
+ </message>
+ <message>
+ <source>User Interface &amp;language:</source>
+ <translation>User Interface &amp;language:</translation>
+ </message>
+ <message>
+ <source>The user interface language can be set here. This setting will take effect after restarting %1.</source>
+ <translation>The user interface language can be set here. This setting will take effect after restarting %1.</translation>
+ </message>
+ <message>
+ <source>&amp;Unit to show amounts in:</source>
+ <translation>&amp;Unit to show amounts in:</translation>
+ </message>
+ <message>
+ <source>Choose the default subdivision unit to show in the interface and when sending coins.</source>
+ <translation>Choose the default subdivision unit to show in the interface and when sending coins.</translation>
+ </message>
+ <message>
+ <source>Whether to show coin control features or not.</source>
+ <translation>Whether to show coin control features or not.</translation>
+ </message>
+ <message>
+ <source>&amp;Third party transaction URLs</source>
+ <translation>&amp;Third party transaction URLs</translation>
+ </message>
+ <message>
+ <source>Options set in this dialog are overridden by the command line or in the configuration file:</source>
+ <translation>Options set in this dialog are overridden by the command line or in the configuration file:</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>&amp;OK</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>&amp;Cancel</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>default</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>none</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>Confirm options reset</translation>
+ </message>
+ <message>
+ <source>Client restart required to activate changes.</source>
+ <translation>Client restart required to activate changes.</translation>
+ </message>
+ <message>
+ <source>Client will be shut down. Do you want to proceed?</source>
+ <translation>Client will be shut down. Do you want to proceed?</translation>
+ </message>
+ <message>
+ <source>Configuration options</source>
+ <translation>Configuration options</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>
+ <translation>The configuration file is used to specify advanced user options which override GUI settings. Additionally, any command-line options will override this configuration file.</translation>
+ </message>
+ <message>
<source>Error</source>
<translation>Ralat</translation>
</message>
- </context>
+ <message>
+ <source>The configuration file could not be opened.</source>
+ <translation>The configuration file could not be opened.</translation>
+ </message>
+ <message>
+ <source>This change would require a client restart.</source>
+ <translation>This change would require a client restart.</translation>
+ </message>
+ <message>
+ <source>The supplied proxy address is invalid.</source>
+ <translation>The supplied proxy address is invalid.</translation>
+ </message>
+</context>
<context>
<name>OverviewPage</name>
+ <message>
+ <source>Form</source>
+ <translation>Form</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>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.</translation>
+ </message>
+ <message>
+ <source>Watch-only:</source>
+ <translation>Watch-only:</translation>
+ </message>
+ <message>
+ <source>Available:</source>
+ <translation>Available:</translation>
+ </message>
+ <message>
+ <source>Your current spendable balance</source>
+ <translation>Your current spendable balance</translation>
+ </message>
+ <message>
+ <source>Pending:</source>
+ <translation>Pending:</translation>
+ </message>
+ <message>
+ <source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
+ <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</translation>
+ </message>
+ <message>
+ <source>Immature:</source>
+ <translation>Immature:</translation>
+ </message>
+ <message>
+ <source>Mined balance that has not yet matured</source>
+ <translation>Mined balance that has not yet matured</translation>
+ </message>
+ <message>
+ <source>Balances</source>
+ <translation>Balances</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Total:</translation>
+ </message>
+ <message>
+ <source>Your current total balance</source>
+ <translation>Your current total balance</translation>
+ </message>
+ <message>
+ <source>Your current balance in watch-only addresses</source>
+ <translation>Your current balance in watch-only addresses</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Spendable:</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Recent transactions</translation>
+ </message>
+ <message>
+ <source>Unconfirmed transactions to watch-only addresses</source>
+ <translation>Unconfirmed transactions to watch-only addresses</translation>
+ </message>
+ <message>
+ <source>Mined balance in watch-only addresses that has not yet matured</source>
+ <translation>Mined balance in watch-only addresses that has not yet matured</translation>
+ </message>
+ <message>
+ <source>Current total balance in watch-only addresses</source>
+ <translation>Current total balance in watch-only addresses</translation>
+ </message>
</context>
<context>
- <name>PaymentServer</name>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Total Amount</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>or</translation>
+ </message>
</context>
<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Payment request error</translation>
+ </message>
+ <message>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
+ <translation>Cannot start bitcoin: click-to-pay handler</translation>
+ </message>
+ <message>
+ <source>URI handling</source>
+ <translation>URI handling</translation>
+ </message>
+ <message>
+ <source>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</source>
+ <translation>'bitcoin://' is not a valid URI. Use 'bitcoin:' instead.</translation>
+ </message>
+ <message>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>Cannot process payment request because BIP70 is not supported.</translation>
+ </message>
+ <message>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</translation>
+ </message>
+ <message>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</translation>
+ </message>
+ <message>
+ <source>Invalid payment address %1</source>
+ <translation>Invalid payment address %1</translation>
+ </message>
+ <message>
+ <source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
+ <translation>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation>
+ </message>
+ <message>
+ <source>Payment request file handling</source>
+ <translation>Payment request file handling</translation>
+ </message>
+</context>
+<context>
<name>PeerTableModel</name>
- </context>
+ <message>
+ <source>User Agent</source>
+ <translation>User Agent</translation>
+ </message>
+ <message>
+ <source>Node/Service</source>
+ <translation>Node/Service</translation>
+ </message>
+ <message>
+ <source>NodeId</source>
+ <translation>NodeId</translation>
+ </message>
+ <message>
+ <source>Ping</source>
+ <translation>Ping</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Sent</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Received</translation>
+ </message>
+</context>
<context>
<name>QObject</name>
<message>
<source>Amount</source>
<translation>Amount</translation>
</message>
- </context>
+ <message>
+ <source>Enter a Bitcoin address (e.g. %1)</source>
+ <translation>Enter a Bitcoin address (e.g. %1)</translation>
+ </message>
+ <message>
+ <source>%1 d</source>
+ <translation>%1 d</translation>
+ </message>
+ <message>
+ <source>%1 h</source>
+ <translation>%1 h</translation>
+ </message>
+ <message>
+ <source>%1 m</source>
+ <translation>%1 m</translation>
+ </message>
+ <message>
+ <source>%1 s</source>
+ <translation>%1 s</translation>
+ </message>
+ <message>
+ <source>None</source>
+ <translation>None</translation>
+ </message>
+ <message>
+ <source>N/A</source>
+ <translation>N/A</translation>
+ </message>
+ <message>
+ <source>%1 ms</source>
+ <translation>%1 ms</translation>
+ </message>
+ <message>
+ <source>%1 and %2</source>
+ <translation>%1 and %2</translation>
+ </message>
+ <message>
+ <source>%1 B</source>
+ <translation>%1 B</translation>
+ </message>
+ <message>
+ <source>%1 KB</source>
+ <translation>%1 KB</translation>
+ </message>
+ <message>
+ <source>%1 MB</source>
+ <translation>%1 MB</translation>
+ </message>
+ <message>
+ <source>%1 GB</source>
+ <translation>%1 GB</translation>
+ </message>
+ <message>
+ <source>Error: Specified data directory "%1" does not exist.</source>
+ <translation>Error: Specified data directory "%1" does not exist.</translation>
+ </message>
+ <message>
+ <source>Error: Cannot parse configuration file: %1.</source>
+ <translation>Error: Cannot parse configuration file: %1.</translation>
+ </message>
+ <message>
+ <source>Error: %1</source>
+ <translation>Error: %1</translation>
+ </message>
+ <message>
+ <source>%1 didn't yet exit safely...</source>
+ <translation>%1 didn't yet exit safely...</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>unknown</translation>
+ </message>
+</context>
<context>
<name>QRImageWidget</name>
- </context>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Save Image...</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Image</source>
+ <translation>&amp;Copy Image</translation>
+ </message>
+ <message>
+ <source>Resulting URI too long, try to reduce the text for label / message.</source>
+ <translation>Resulting URI too long, try to reduce the text for label / message.</translation>
+ </message>
+ <message>
+ <source>Error encoding URI into QR Code.</source>
+ <translation>Error encoding URI into QR Code.</translation>
+ </message>
+ <message>
+ <source>QR code support not available.</source>
+ <translation>QR code support not available.</translation>
+ </message>
+ <message>
+ <source>Save QR Code</source>
+ <translation>Save QR Code</translation>
+ </message>
+ <message>
+ <source>PNG Image (*.png)</source>
+ <translation>PNG Image (*.png)</translation>
+ </message>
+</context>
<context>
<name>RPCConsole</name>
- </context>
+ <message>
+ <source>N/A</source>
+ <translation>N/A</translation>
+ </message>
+ <message>
+ <source>Client version</source>
+ <translation>Client version</translation>
+ </message>
+ <message>
+ <source>&amp;Information</source>
+ <translation>&amp;Information</translation>
+ </message>
+ <message>
+ <source>General</source>
+ <translation>General</translation>
+ </message>
+ <message>
+ <source>Using BerkeleyDB version</source>
+ <translation>Using BerkeleyDB version</translation>
+ </message>
+ <message>
+ <source>Datadir</source>
+ <translation>Datadir</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the data directory use the '%1' option.</source>
+ <translation>To specify a non-default location of the data directory use the '%1' option.</translation>
+ </message>
+ <message>
+ <source>Blocksdir</source>
+ <translation>Blocksdir</translation>
+ </message>
+ <message>
+ <source>To specify a non-default location of the blocks directory use the '%1' option.</source>
+ <translation>To specify a non-default location of the blocks directory use the '%1' option.</translation>
+ </message>
+ <message>
+ <source>Startup time</source>
+ <translation>Startup time</translation>
+ </message>
+ <message>
+ <source>Network</source>
+ <translation>Network</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>Name</translation>
+ </message>
+ <message>
+ <source>Number of connections</source>
+ <translation>Number of connections</translation>
+ </message>
+ <message>
+ <source>Block chain</source>
+ <translation>Block chain</translation>
+ </message>
+ <message>
+ <source>Memory Pool</source>
+ <translation>Memory Pool</translation>
+ </message>
+ <message>
+ <source>Current number of transactions</source>
+ <translation>Current number of transactions</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Memory usage</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>Wallet: </translation>
+ </message>
+ <message>
+ <source>(none)</source>
+ <translation>(none)</translation>
+ </message>
+ <message>
+ <source>&amp;Reset</source>
+ <translation>&amp;Reset</translation>
+ </message>
+ <message>
+ <source>Received</source>
+ <translation>Received</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Sent</translation>
+ </message>
+ <message>
+ <source>&amp;Peers</source>
+ <translation>&amp;Peers</translation>
+ </message>
+ <message>
+ <source>Banned peers</source>
+ <translation>Banned peers</translation>
+ </message>
+ <message>
+ <source>Select a peer to view detailed information.</source>
+ <translation>Select a peer to view detailed information.</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Direction</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>Version</translation>
+ </message>
+ <message>
+ <source>Starting Block</source>
+ <translation>Starting Block</translation>
+ </message>
+ <message>
+ <source>Synced Headers</source>
+ <translation>Synced Headers</translation>
+ </message>
+ <message>
+ <source>Synced Blocks</source>
+ <translation>Synced Blocks</translation>
+ </message>
+ <message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation>The mapped Autonomous System used for diversifying peer selection.</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation>Mapped AS</translation>
+ </message>
+ <message>
+ <source>User Agent</source>
+ <translation>User Agent</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation>Node window</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>Open the %1 debug log file from the current data directory. This can take a few seconds for large log files.</translation>
+ </message>
+ <message>
+ <source>Decrease font size</source>
+ <translation>Decrease font size</translation>
+ </message>
+ <message>
+ <source>Increase font size</source>
+ <translation>Increase font size</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Services</translation>
+ </message>
+ <message>
+ <source>Connection Time</source>
+ <translation>Connection Time</translation>
+ </message>
+ <message>
+ <source>Last Send</source>
+ <translation>Last Send</translation>
+ </message>
+ <message>
+ <source>Last Receive</source>
+ <translation>Last Receive</translation>
+ </message>
+ <message>
+ <source>Ping Time</source>
+ <translation>Ping Time</translation>
+ </message>
+ <message>
+ <source>The duration of a currently outstanding ping.</source>
+ <translation>The duration of a currently outstanding ping.</translation>
+ </message>
+ <message>
+ <source>Ping Wait</source>
+ <translation>Ping Wait</translation>
+ </message>
+ <message>
+ <source>Min Ping</source>
+ <translation>Min Ping</translation>
+ </message>
+ <message>
+ <source>Time Offset</source>
+ <translation>Time Offset</translation>
+ </message>
+ <message>
+ <source>Last block time</source>
+ <translation>Last block time</translation>
+ </message>
+ <message>
+ <source>&amp;Open</source>
+ <translation>&amp;Open</translation>
+ </message>
+ <message>
+ <source>&amp;Console</source>
+ <translation>&amp;Console</translation>
+ </message>
+ <message>
+ <source>&amp;Network Traffic</source>
+ <translation>&amp;Network Traffic</translation>
+ </message>
+ <message>
+ <source>Totals</source>
+ <translation>Totals</translation>
+ </message>
+ <message>
+ <source>In:</source>
+ <translation>In:</translation>
+ </message>
+ <message>
+ <source>Out:</source>
+ <translation>Out:</translation>
+ </message>
+ <message>
+ <source>Debug log file</source>
+ <translation>Debug log file</translation>
+ </message>
+ <message>
+ <source>Clear console</source>
+ <translation>Clear console</translation>
+ </message>
+ <message>
+ <source>1 &amp;hour</source>
+ <translation>1 &amp;hour</translation>
+ </message>
+ <message>
+ <source>1 &amp;day</source>
+ <translation>1 &amp;day</translation>
+ </message>
+ <message>
+ <source>1 &amp;week</source>
+ <translation>1 &amp;week</translation>
+ </message>
+ <message>
+ <source>1 &amp;year</source>
+ <translation>1 &amp;year</translation>
+ </message>
+ <message>
+ <source>&amp;Disconnect</source>
+ <translation>&amp;Disconnect</translation>
+ </message>
+ <message>
+ <source>Ban for</source>
+ <translation>Ban for</translation>
+ </message>
+ <message>
+ <source>&amp;Unban</source>
+ <translation>&amp;Unban</translation>
+ </message>
+ <message>
+ <source>Welcome to the %1 RPC console.</source>
+ <translation>Welcome to the %1 RPC console.</translation>
+ </message>
+ <message>
+ <source>Use up and down arrows to navigate history, and %1 to clear screen.</source>
+ <translation>Use up and down arrows to navigate history, and %1 to clear screen.</translation>
+ </message>
+ <message>
+ <source>Type %1 for an overview of available commands.</source>
+ <translation>Type %1 for an overview of available commands.</translation>
+ </message>
+ <message>
+ <source>For more information on using this console type %1.</source>
+ <translation>For more information on using this console type %1.</translation>
+ </message>
+ <message>
+ <source>WARNING: 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.</source>
+ <translation>WARNING: 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.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled</source>
+ <translation>Network activity disabled</translation>
+ </message>
+ <message>
+ <source>Executing command without any wallet</source>
+ <translation>Executing command without any wallet</translation>
+ </message>
+ <message>
+ <source>Executing command using "%1" wallet</source>
+ <translation>Executing command using "%1" wallet</translation>
+ </message>
+ <message>
+ <source>(node id: %1)</source>
+ <translation>(node id: %1)</translation>
+ </message>
+ <message>
+ <source>via %1</source>
+ <translation>via %1</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>never</translation>
+ </message>
+ <message>
+ <source>Inbound</source>
+ <translation>Inbound</translation>
+ </message>
+ <message>
+ <source>Outbound</source>
+ <translation>Outbound</translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>Unknown</translation>
+ </message>
+</context>
<context>
<name>ReceiveCoinsDialog</name>
+ <message>
+ <source>&amp;Amount:</source>
+ <translation>&amp;Amount:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Label:</translation>
+ </message>
+ <message>
+ <source>&amp;Message:</source>
+ <translation>&amp;Message:</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>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.</translation>
+ </message>
+ <message>
+ <source>An optional label to associate with the new receiving address.</source>
+ <translation>An optional label to associate with the new receiving address.</translation>
+ </message>
+ <message>
+ <source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
+ <translation>Use this form to request payments. All fields are &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>An optional amount to request. Leave this empty or zero to not request a specific amount.</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>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.</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>An optional message that is attached to the payment request and may be displayed to the sender.</translation>
+ </message>
+ <message>
+ <source>&amp;Create new receiving address</source>
+ <translation>&amp;Create new receiving address</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Clear all fields of the form.</translation>
+ </message>
+ <message>
+ <source>Clear</source>
+ <translation>Clear</translation>
+ </message>
+ <message>
+ <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
+ <translation>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</translation>
+ </message>
+ <message>
+ <source>Generate native segwit (Bech32) address</source>
+ <translation>Generate native segwit (Bech32) address</translation>
+ </message>
+ <message>
+ <source>Requested payments history</source>
+ <translation>Requested payments history</translation>
+ </message>
+ <message>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation>Show the selected request (does the same as double clicking an entry)</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Show</translation>
+ </message>
+ <message>
+ <source>Remove the selected entries from the list</source>
+ <translation>Remove the selected entries from the list</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Remove</translation>
+ </message>
+ <message>
+ <source>Copy URI</source>
+ <translation>Copy URI</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copy label</translation>
+ </message>
+ <message>
+ <source>Copy message</source>
+ <translation>Copy message</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copy amount</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Could not unlock wallet.</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Salin Alamat</translation>
+ <source>Amount:</source>
+ <translation>Amount:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Alamat</translation>
+ <source>Message:</source>
+ <translation>Message:</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Amount</translation>
+ <source>Wallet:</source>
+ <translation>dompet</translation>
</message>
<message>
- <source>Label</source>
- <translation>Label</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copy &amp;URI</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>dompet</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Salin Alamat</translation>
+ </message>
+ <message>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Save Image...</translation>
+ </message>
+ <message>
+ <source>Request payment to %1</source>
+ <translation>Request payment to %1</translation>
+ </message>
+ <message>
+ <source>Payment information</source>
+ <translation>Payment information</translation>
</message>
</context>
<context>
<name>RecentRequestsTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Date</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Label</translation>
</message>
<message>
+ <source>Message</source>
+ <translation>Message</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tiada label)</translation>
</message>
- </context>
+ <message>
+ <source>(no message)</source>
+ <translation>(no message)</translation>
+ </message>
+ <message>
+ <source>(no amount requested)</source>
+ <translation>(no amount requested)</translation>
+ </message>
+ <message>
+ <source>Requested</source>
+ <translation>Requested</translation>
+ </message>
+</context>
<context>
<name>SendCoinsDialog</name>
<message>
+ <source>Send Coins</source>
+ <translation>Send Coins</translation>
+ </message>
+ <message>
+ <source>Coin Control Features</source>
+ <translation>Coin Control Features</translation>
+ </message>
+ <message>
+ <source>Inputs...</source>
+ <translation>Inputs...</translation>
+ </message>
+ <message>
+ <source>automatically selected</source>
+ <translation>automatically selected</translation>
+ </message>
+ <message>
+ <source>Insufficient funds!</source>
+ <translation>Insufficient funds!</translation>
+ </message>
+ <message>
+ <source>Quantity:</source>
+ <translation>Quantity:</translation>
+ </message>
+ <message>
+ <source>Bytes:</source>
+ <translation>Bytes:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Amount:</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Fee:</translation>
+ </message>
+ <message>
+ <source>After Fee:</source>
+ <translation>After Fee:</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Change:</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>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</translation>
+ </message>
+ <message>
+ <source>Custom change address</source>
+ <translation>Custom change address</translation>
+ </message>
+ <message>
+ <source>Transaction Fee:</source>
+ <translation>Transaction Fee:</translation>
+ </message>
+ <message>
+ <source>Choose...</source>
+ <translation>Choose...</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>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.</translation>
+ </message>
+ <message>
+ <source>Warning: Fee estimation is currently not possible.</source>
+ <translation>Warning: Fee estimation is currently not possible.</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 of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</source>
+ <translation>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 of "100 satoshis per kB" for a transaction size of 500 bytes (half of 1 kB) would ultimately yield a fee of only 50 satoshis.</translation>
+ </message>
+ <message>
+ <source>per kilobyte</source>
+ <translation>per kilobyte</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Hide</translation>
+ </message>
+ <message>
+ <source>Recommended:</source>
+ <translation>Recommended:</translation>
+ </message>
+ <message>
+ <source>Custom:</source>
+ <translation>Custom:</translation>
+ </message>
+ <message>
+ <source>(Smart fee not initialized yet. This usually takes a few blocks...)</source>
+ <translation>(Smart fee not initialized yet. This usually takes a few blocks...)</translation>
+ </message>
+ <message>
+ <source>Send to multiple recipients at once</source>
+ <translation>Send to multiple recipients at once</translation>
+ </message>
+ <message>
+ <source>Add &amp;Recipient</source>
+ <translation>Add &amp;Recipient</translation>
+ </message>
+ <message>
+ <source>Clear all fields of the form.</source>
+ <translation>Clear all fields of the form.</translation>
+ </message>
+ <message>
+ <source>Dust:</source>
+ <translation>Dust:</translation>
+ </message>
+ <message>
+ <source>Hide transaction fee settings</source>
+ <translation>Hide transaction fee settings</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>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.</translation>
+ </message>
+ <message>
+ <source>A too low fee might result in a never confirming transaction (read the tooltip)</source>
+ <translation>A too low fee might result in a never confirming transaction (read the tooltip)</translation>
+ </message>
+ <message>
+ <source>Confirmation time target:</source>
+ <translation>Confirmation time target:</translation>
+ </message>
+ <message>
+ <source>Enable Replace-By-Fee</source>
+ <translation>Enable 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>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.</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Clear &amp;All</translation>
+ </message>
+ <message>
<source>Balance:</source>
<translation>Baki</translation>
</message>
<message>
+ <source>Confirm the send action</source>
+ <translation>Confirm the send action</translation>
+ </message>
+ <message>
+ <source>S&amp;end</source>
+ <translation>S&amp;end</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Copy quantity</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copy amount</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Copy fee</translation>
+ </message>
+ <message>
+ <source>Copy after fee</source>
+ <translation>Copy after fee</translation>
+ </message>
+ <message>
+ <source>Copy bytes</source>
+ <translation>Copy bytes</translation>
+ </message>
+ <message>
+ <source>Copy dust</source>
+ <translation>Copy dust</translation>
+ </message>
+ <message>
+ <source>Copy change</source>
+ <translation>Copy change</translation>
+ </message>
+ <message>
+ <source>%1 (%2 blocks)</source>
+ <translation>%1 (%2 blocks)</translation>
+ </message>
+ <message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Cr&amp;eate Unsigned</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>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
+ </message>
+ <message>
+ <source> from wallet '%1'</source>
+ <translation> from wallet '%1'</translation>
+ </message>
+ <message>
+ <source>%1 to '%2'</source>
+ <translation>%1 to '%2'</translation>
+ </message>
+ <message>
+ <source>%1 to %2</source>
+ <translation>%1 to %2</translation>
+ </message>
+ <message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>Do you want to draft this transaction?</translation>
+ </message>
+ <message>
+ <source>Are you sure you want to send?</source>
+ <translation>Are you sure you want to send?</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>or</translation>
+ </message>
+ <message>
+ <source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
+ <translation>You can increase the fee later (signals Replace-By-Fee, BIP-125).</translation>
+ </message>
+ <message>
+ <source>Please, review your transaction.</source>
+ <translation>Please, review your transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaction fee</translation>
+ </message>
+ <message>
+ <source>Not signalling Replace-By-Fee, BIP-125.</source>
+ <translation>Not signalling Replace-By-Fee, BIP-125.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Total Amount</translation>
+ </message>
+ <message>
+ <source>To review recipient list click "Show Details..."</source>
+ <translation>To review recipient list click "Show Details..."</translation>
+ </message>
+ <message>
+ <source>Confirm send coins</source>
+ <translation>Confirm send coins</translation>
+ </message>
+ <message>
+ <source>Confirm transaction proposal</source>
+ <translation>Confirm transaction proposal</translation>
+ </message>
+ <message>
+ <source>Send</source>
+ <translation>Send</translation>
+ </message>
+ <message>
+ <source>Watch-only balance:</source>
+ <translation>Watch-only balance:</translation>
+ </message>
+ <message>
+ <source>The recipient address is not valid. Please recheck.</source>
+ <translation>The recipient address is not valid. Please recheck.</translation>
+ </message>
+ <message>
+ <source>The amount to pay must be larger than 0.</source>
+ <translation>The amount to pay must be larger than 0.</translation>
+ </message>
+ <message>
+ <source>The amount exceeds your balance.</source>
+ <translation>The amount exceeds your balance.</translation>
+ </message>
+ <message>
+ <source>The total exceeds your balance when the %1 transaction fee is included.</source>
+ <translation>The total exceeds your balance when the %1 transaction fee is included.</translation>
+ </message>
+ <message>
+ <source>Duplicate address found: addresses should only be used once each.</source>
+ <translation>Duplicate address found: addresses should only be used once each.</translation>
+ </message>
+ <message>
+ <source>Transaction creation failed!</source>
+ <translation>Transaction creation failed!</translation>
+ </message>
+ <message>
+ <source>A fee higher than %1 is considered an absurdly high fee.</source>
+ <translation>A fee higher than %1 is considered an absurdly high fee.</translation>
+ </message>
+ <message>
+ <source>Payment request expired.</source>
+ <translation>Payment request expired.</translation>
+ </message>
+ <message>
+ <source>Warning: Invalid Bitcoin address</source>
+ <translation>Warning: Invalid Bitcoin address</translation>
+ </message>
+ <message>
+ <source>Warning: Unknown change address</source>
+ <translation>Warning: Unknown change address</translation>
+ </message>
+ <message>
+ <source>Confirm custom change address</source>
+ <translation>Confirm custom 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>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?</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tiada label)</translation>
</message>
</context>
<context>
<name>SendCoinsEntry</name>
- </context>
+ <message>
+ <source>A&amp;mount:</source>
+ <translation>A&amp;mount:</translation>
+ </message>
+ <message>
+ <source>Pay &amp;To:</source>
+ <translation>Pay &amp;To:</translation>
+ </message>
+ <message>
+ <source>&amp;Label:</source>
+ <translation>&amp;Label:</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Choose previously used address</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to send the payment to</source>
+ <translation>The Bitcoin address to send the payment to</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Paste address from clipboard</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Remove this entry</source>
+ <translation>Remove this entry</translation>
+ </message>
+ <message>
+ <source>The amount to send in the selected unit</source>
+ <translation>The amount to send in the selected unit</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>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.</translation>
+ </message>
+ <message>
+ <source>S&amp;ubtract fee from amount</source>
+ <translation>S&amp;ubtract fee from amount</translation>
+ </message>
+ <message>
+ <source>Use available balance</source>
+ <translation>Use available balance</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Message:</translation>
+ </message>
+ <message>
+ <source>This is an unauthenticated payment request.</source>
+ <translation>This is an unauthenticated payment request.</translation>
+ </message>
+ <message>
+ <source>This is an authenticated payment request.</source>
+ <translation>This is an authenticated payment request.</translation>
+ </message>
+ <message>
+ <source>Enter a label for this address to add it to the list of used addresses</source>
+ <translation>Enter a label for this address to add it to the list of used addresses</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>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.</translation>
+ </message>
+ <message>
+ <source>Pay To:</source>
+ <translation>Pay To:</translation>
+ </message>
+ <message>
+ <source>Memo:</source>
+ <translation>Memo:</translation>
+ </message>
+</context>
<context>
<name>ShutdownWindow</name>
- </context>
+ <message>
+ <source>%1 is shutting down...</source>
+ <translation>%1 is shutting down...</translation>
+ </message>
+ <message>
+ <source>Do not shut down the computer until this window disappears.</source>
+ <translation>Do not shut down the computer until this window disappears.</translation>
+ </message>
+</context>
<context>
<name>SignVerifyMessageDialog</name>
- </context>
+ <message>
+ <source>Signatures - Sign / Verify a Message</source>
+ <translation>Signatures - Sign / Verify a Message</translation>
+ </message>
+ <message>
+ <source>&amp;Sign Message</source>
+ <translation>&amp;Sign Message</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>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.</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address to sign the message with</source>
+ <translation>The Bitcoin address to sign the message with</translation>
+ </message>
+ <message>
+ <source>Choose previously used address</source>
+ <translation>Choose previously used address</translation>
+ </message>
+ <message>
+ <source>Alt+A</source>
+ <translation>Alt+A</translation>
+ </message>
+ <message>
+ <source>Paste address from clipboard</source>
+ <translation>Paste address from clipboard</translation>
+ </message>
+ <message>
+ <source>Alt+P</source>
+ <translation>Alt+P</translation>
+ </message>
+ <message>
+ <source>Enter the message you want to sign here</source>
+ <translation>Enter the message you want to sign here</translation>
+ </message>
+ <message>
+ <source>Signature</source>
+ <translation>Signature</translation>
+ </message>
+ <message>
+ <source>Copy the current signature to the system clipboard</source>
+ <translation>Copy the current signature to the system clipboard</translation>
+ </message>
+ <message>
+ <source>Sign the message to prove you own this Bitcoin address</source>
+ <translation>Sign the message to prove you own this Bitcoin address</translation>
+ </message>
+ <message>
+ <source>Sign &amp;Message</source>
+ <translation>Sign &amp;Message</translation>
+ </message>
+ <message>
+ <source>Reset all sign message fields</source>
+ <translation>Reset all sign message fields</translation>
+ </message>
+ <message>
+ <source>Clear &amp;All</source>
+ <translation>Clear &amp;All</translation>
+ </message>
+ <message>
+ <source>&amp;Verify Message</source>
+ <translation>&amp;Verify Message</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>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!</translation>
+ </message>
+ <message>
+ <source>The Bitcoin address the message was signed with</source>
+ <translation>The Bitcoin address the message was signed with</translation>
+ </message>
+ <message>
+ <source>The signed message to verify</source>
+ <translation>The signed message to verify</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>The signature given when the message was signed</translation>
+ </message>
+ <message>
+ <source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
+ <translation>Verify the message to ensure it was signed with the specified Bitcoin address</translation>
+ </message>
+ <message>
+ <source>Verify &amp;Message</source>
+ <translation>Verify &amp;Message</translation>
+ </message>
+ <message>
+ <source>Reset all verify message fields</source>
+ <translation>Reset all verify message fields</translation>
+ </message>
+ <message>
+ <source>Click "Sign Message" to generate signature</source>
+ <translation>Click "Sign Message" to generate signature</translation>
+ </message>
+ <message>
+ <source>The entered address is invalid.</source>
+ <translation>The entered address is invalid.</translation>
+ </message>
+ <message>
+ <source>Please check the address and try again.</source>
+ <translation>Please check the address and try again.</translation>
+ </message>
+ <message>
+ <source>The entered address does not refer to a key.</source>
+ <translation>The entered address does not refer to a key.</translation>
+ </message>
+ <message>
+ <source>Wallet unlock was cancelled.</source>
+ <translation>Wallet unlock was cancelled.</translation>
+ </message>
+ <message>
+ <source>No error</source>
+ <translation>No error</translation>
+ </message>
+ <message>
+ <source>Private key for the entered address is not available.</source>
+ <translation>Private key for the entered address is not available.</translation>
+ </message>
+ <message>
+ <source>Message signing failed.</source>
+ <translation>Message signing failed.</translation>
+ </message>
+ <message>
+ <source>Message signed.</source>
+ <translation>Message signed.</translation>
+ </message>
+ <message>
+ <source>The signature could not be decoded.</source>
+ <translation>The signature could not be decoded.</translation>
+ </message>
+ <message>
+ <source>Please check the signature and try again.</source>
+ <translation>Please check the signature and try again.</translation>
+ </message>
+ <message>
+ <source>The signature did not match the message digest.</source>
+ <translation>The signature did not match the message digest.</translation>
+ </message>
+ <message>
+ <source>Message verification failed.</source>
+ <translation>Message verification failed.</translation>
+ </message>
+ <message>
+ <source>Message verified.</source>
+ <translation>Message verified.</translation>
+ </message>
+</context>
<context>
<name>TrafficGraphWidget</name>
- </context>
+ <message>
+ <source>KB/s</source>
+ <translation>KB/s</translation>
+ </message>
+</context>
<context>
<name>TransactionDesc</name>
<message>
+ <source>Open until %1</source>
+ <translation>Open until %1</translation>
+ </message>
+ <message>
+ <source>conflicted with a transaction with %1 confirmations</source>
+ <translation>conflicted with a transaction with %1 confirmations</translation>
+ </message>
+ <message>
+ <source>0/unconfirmed, %1</source>
+ <translation>0/unconfirmed, %1</translation>
+ </message>
+ <message>
+ <source>in memory pool</source>
+ <translation>in memory pool</translation>
+ </message>
+ <message>
+ <source>not in memory pool</source>
+ <translation>not in memory pool</translation>
+ </message>
+ <message>
+ <source>abandoned</source>
+ <translation>abandoned</translation>
+ </message>
+ <message>
+ <source>%1/unconfirmed</source>
+ <translation>%1/unconfirmed</translation>
+ </message>
+ <message>
+ <source>%1 confirmations</source>
+ <translation>%1 confirmations</translation>
+ </message>
+ <message>
+ <source>Status</source>
+ <translation>Status</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Date</translation>
+ </message>
+ <message>
+ <source>Source</source>
+ <translation>Source</translation>
+ </message>
+ <message>
+ <source>Generated</source>
+ <translation>Generated</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>From</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>unknown</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>To</translation>
+ </message>
+ <message>
+ <source>own address</source>
+ <translation>own address</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>watch-only</translation>
+ </message>
+ <message>
+ <source>label</source>
+ <translation>label</translation>
+ </message>
+ <message>
+ <source>Credit</source>
+ <translation>Credit</translation>
+ </message>
+ <message>
+ <source>not accepted</source>
+ <translation>not accepted</translation>
+ </message>
+ <message>
+ <source>Debit</source>
+ <translation>Debit</translation>
+ </message>
+ <message>
+ <source>Total debit</source>
+ <translation>Total debit</translation>
+ </message>
+ <message>
+ <source>Total credit</source>
+ <translation>Total credit</translation>
+ </message>
+ <message>
+ <source>Transaction fee</source>
+ <translation>Transaction fee</translation>
+ </message>
+ <message>
+ <source>Net amount</source>
+ <translation>Net amount</translation>
+ </message>
+ <message>
+ <source>Message</source>
+ <translation>Message</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Comment</translation>
+ </message>
+ <message>
+ <source>Transaction ID</source>
+ <translation>Transaction ID</translation>
+ </message>
+ <message>
+ <source>Transaction total size</source>
+ <translation>Transaction total size</translation>
+ </message>
+ <message>
+ <source>Transaction virtual size</source>
+ <translation>Transaction virtual size</translation>
+ </message>
+ <message>
+ <source>Output index</source>
+ <translation>Output index</translation>
+ </message>
+ <message>
+ <source> (Certificate was not verified)</source>
+ <translation> (Certificate was not verified)</translation>
+ </message>
+ <message>
+ <source>Merchant</source>
+ <translation>Merchant</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>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.</translation>
+ </message>
+ <message>
+ <source>Debug information</source>
+ <translation>Debug information</translation>
+ </message>
+ <message>
+ <source>Transaction</source>
+ <translation>Transaction</translation>
+ </message>
+ <message>
+ <source>Inputs</source>
+ <translation>Inputs</translation>
+ </message>
+ <message>
<source>Amount</source>
<translation>Amount</translation>
</message>
- </context>
+ <message>
+ <source>true</source>
+ <translation>true</translation>
+ </message>
+ <message>
+ <source>false</source>
+ <translation>false</translation>
+ </message>
+</context>
<context>
<name>TransactionDescDialog</name>
- </context>
+ <message>
+ <source>This pane shows a detailed description of the transaction</source>
+ <translation>This pane shows a detailed description of the transaction</translation>
+ </message>
+ <message>
+ <source>Details for %1</source>
+ <translation>Details for %1</translation>
+ </message>
+</context>
<context>
<name>TransactionTableModel</name>
<message>
+ <source>Date</source>
+ <translation>Date</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Type</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Label</translation>
</message>
<message>
+ <source>Open until %1</source>
+ <translation>Open until %1</translation>
+ </message>
+ <message>
+ <source>Unconfirmed</source>
+ <translation>Unconfirmed</translation>
+ </message>
+ <message>
+ <source>Abandoned</source>
+ <translation>Abandoned</translation>
+ </message>
+ <message>
+ <source>Confirming (%1 of %2 recommended confirmations)</source>
+ <translation>Confirming (%1 of %2 recommended confirmations)</translation>
+ </message>
+ <message>
+ <source>Confirmed (%1 confirmations)</source>
+ <translation>Confirmed (%1 confirmations)</translation>
+ </message>
+ <message>
+ <source>Conflicted</source>
+ <translation>Conflicted</translation>
+ </message>
+ <message>
+ <source>Immature (%1 confirmations, will be available after %2)</source>
+ <translation>Immature (%1 confirmations, will be available after %2)</translation>
+ </message>
+ <message>
+ <source>Generated but not accepted</source>
+ <translation>Generated but not accepted</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Received with</translation>
+ </message>
+ <message>
+ <source>Received from</source>
+ <translation>Received from</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Sent to</translation>
+ </message>
+ <message>
+ <source>Payment to yourself</source>
+ <translation>Payment to yourself</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Mined</translation>
+ </message>
+ <message>
+ <source>watch-only</source>
+ <translation>watch-only</translation>
+ </message>
+ <message>
+ <source>(n/a)</source>
+ <translation>(n/a)</translation>
+ </message>
+ <message>
<source>(no label)</source>
<translation>(tiada label)</translation>
</message>
- </context>
+ <message>
+ <source>Transaction status. Hover over this field to show number of confirmations.</source>
+ <translation>Transaction status. Hover over this field to show number of confirmations.</translation>
+ </message>
+ <message>
+ <source>Date and time that the transaction was received.</source>
+ <translation>Date and time that the transaction was received.</translation>
+ </message>
+ <message>
+ <source>Type of transaction.</source>
+ <translation>Type of transaction.</translation>
+ </message>
+ <message>
+ <source>Whether or not a watch-only address is involved in this transaction.</source>
+ <translation>Whether or not a watch-only address is involved in this transaction.</translation>
+ </message>
+ <message>
+ <source>User-defined intent/purpose of the transaction.</source>
+ <translation>User-defined intent/purpose of the transaction.</translation>
+ </message>
+ <message>
+ <source>Amount removed from or added to balance.</source>
+ <translation>Amount removed from or added to balance.</translation>
+ </message>
+</context>
<context>
<name>TransactionView</name>
<message>
+ <source>All</source>
+ <translation>All</translation>
+ </message>
+ <message>
+ <source>Today</source>
+ <translation>Today</translation>
+ </message>
+ <message>
+ <source>This week</source>
+ <translation>This week</translation>
+ </message>
+ <message>
+ <source>This month</source>
+ <translation>This month</translation>
+ </message>
+ <message>
+ <source>Last month</source>
+ <translation>Last month</translation>
+ </message>
+ <message>
+ <source>This year</source>
+ <translation>This year</translation>
+ </message>
+ <message>
+ <source>Range...</source>
+ <translation>Range...</translation>
+ </message>
+ <message>
+ <source>Received with</source>
+ <translation>Received with</translation>
+ </message>
+ <message>
+ <source>Sent to</source>
+ <translation>Sent to</translation>
+ </message>
+ <message>
+ <source>To yourself</source>
+ <translation>To yourself</translation>
+ </message>
+ <message>
+ <source>Mined</source>
+ <translation>Mined</translation>
+ </message>
+ <message>
+ <source>Other</source>
+ <translation>Other</translation>
+ </message>
+ <message>
+ <source>Enter address, transaction id, or label to search</source>
+ <translation>Enter address, transaction id, or label to search</translation>
+ </message>
+ <message>
+ <source>Min amount</source>
+ <translation>Min amount</translation>
+ </message>
+ <message>
+ <source>Abandon transaction</source>
+ <translation>Abandon transaction</translation>
+ </message>
+ <message>
+ <source>Increase transaction fee</source>
+ <translation>Increase transaction fee</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Copy address</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Copy label</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Copy amount</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>Copy transaction ID</translation>
+ </message>
+ <message>
+ <source>Copy raw transaction</source>
+ <translation>Copy raw transaction</translation>
+ </message>
+ <message>
+ <source>Copy full transaction details</source>
+ <translation>Copy full transaction details</translation>
+ </message>
+ <message>
+ <source>Edit label</source>
+ <translation>Edit label</translation>
+ </message>
+ <message>
+ <source>Show transaction details</source>
+ <translation>Show transaction details</translation>
+ </message>
+ <message>
+ <source>Export Transaction History</source>
+ <translation>Export Transaction History</translation>
+ </message>
+ <message>
<source>Comma separated file (*.csv)</source>
<translation>Fail dibahagi oleh koma(*.csv)</translation>
</message>
<message>
+ <source>Confirmed</source>
+ <translation>Confirmed</translation>
+ </message>
+ <message>
+ <source>Watch-only</source>
+ <translation>Watch-only</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Date</translation>
+ </message>
+ <message>
+ <source>Type</source>
+ <translation>Type</translation>
+ </message>
+ <message>
<source>Label</source>
<translation>Label</translation>
</message>
@@ -612,26 +3059,118 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>Alamat</translation>
</message>
<message>
+ <source>ID</source>
+ <translation>ID</translation>
+ </message>
+ <message>
<source>Exporting Failed</source>
<translation>Mengeksport Gagal</translation>
</message>
- </context>
+ <message>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation>There was an error trying to save the transaction history to %1.</translation>
+ </message>
+ <message>
+ <source>Exporting Successful</source>
+ <translation>Exporting Successful</translation>
+ </message>
+ <message>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation>The transaction history was successfully saved to %1.</translation>
+ </message>
+ <message>
+ <source>Range:</source>
+ <translation>Range:</translation>
+ </message>
+ <message>
+ <source>to</source>
+ <translation>to</translation>
+ </message>
+</context>
<context>
<name>UnitDisplayStatusBarControl</name>
- </context>
+ <message>
+ <source>Unit to show amounts in. Click to select another unit.</source>
+ <translation>Unit to show amounts in. Click to select another unit.</translation>
+ </message>
+</context>
<context>
<name>WalletController</name>
<message>
<source>Close wallet</source>
<translation>Tutup Wallet</translation>
</message>
+ <message>
+ <source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
+ <translation>Are you sure you wish to close the wallet &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>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Create a new wallet</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
+ <source>Send Coins</source>
+ <translation>Send Coins</translation>
+ </message>
+ <message>
+ <source>Fee bump error</source>
+ <translation>Fee bump error</translation>
+ </message>
+ <message>
+ <source>Increasing transaction fee failed</source>
+ <translation>Increasing transaction fee failed</translation>
+ </message>
+ <message>
+ <source>Do you want to increase the fee?</source>
+ <translation>Do you want to increase the fee?</translation>
+ </message>
+ <message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>Do you want to draft a transaction with fee increase?</translation>
+ </message>
+ <message>
+ <source>Current fee:</source>
+ <translation>Current fee:</translation>
+ </message>
+ <message>
+ <source>Increase:</source>
+ <translation>Increase:</translation>
+ </message>
+ <message>
+ <source>New fee:</source>
+ <translation>New fee:</translation>
+ </message>
+ <message>
+ <source>Confirm fee bump</source>
+ <translation>Confirm fee bump</translation>
+ </message>
+ <message>
+ <source>Can't draft transaction.</source>
+ <translation>Can't draft transaction.</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT copied</translation>
+ </message>
+ <message>
+ <source>Can't sign transaction.</source>
+ <translation>Can't sign transaction.</translation>
+ </message>
+ <message>
+ <source>Could not commit transaction</source>
+ <translation>Could not commit transaction</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>dompet lalai
</translation>
@@ -648,14 +3187,504 @@ Alihkan fail data ke dalam tab semasa</translation>
<translation>
Alihkan fail data ke dalam tab semasa</translation>
</message>
- </context>
+ <message>
+ <source>Error</source>
+ <translation>Ralat</translation>
+ </message>
+ <message>
+ <source>Backup Wallet</source>
+ <translation>Backup Wallet</translation>
+ </message>
+ <message>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Wallet Data (*.dat)</translation>
+ </message>
+ <message>
+ <source>Backup Failed</source>
+ <translation>Backup Failed</translation>
+ </message>
+ <message>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation>There was an error trying to save the wallet data to %1.</translation>
+ </message>
+ <message>
+ <source>Backup Successful</source>
+ <translation>Backup Successful</translation>
+ </message>
+ <message>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation>The wallet data was successfully saved to %1.</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>Cancel</translation>
+ </message>
+</context>
<context>
<name>bitcoin-core</name>
<message>
+ <source>Distributed under the MIT software license, see the accompanying file %s or %s</source>
+ <translation>Distributed under the MIT software license, see the accompanying file %s or %s</translation>
+ </message>
+ <message>
+ <source>Prune configured below the minimum of %d MiB. Please use a higher number.</source>
+ <translation>Prune configured below the minimum of %d MiB. Please use a higher number.</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>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation>
+ </message>
+ <message>
+ <source>Pruning blockstore...</source>
+ <translation>Pruning blockstore...</translation>
+ </message>
+ <message>
+ <source>Unable to start HTTP server. See debug log for details.</source>
+ <translation>Unable to start HTTP server. See debug log for details.</translation>
+ </message>
+ <message>
+ <source>The %s developers</source>
+ <translation>The %s developers</translation>
+ </message>
+ <message>
+ <source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
+ <translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
+ </message>
+ <message>
+ <source>Cannot provide specific connections and have addrman find outgoing connections at the same.</source>
+ <translation>Cannot provide specific connections and have addrman find outgoing connections at the same.</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>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</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>Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.</translation>
+ </message>
+ <message>
+ <source>Please contribute if you find %s useful. Visit %s for further information about the software.</source>
+ <translation>Please contribute if you find %s useful. Visit %s for further information about the software.</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>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</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>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may discard if change is smaller than dust at this level</source>
+ <translation>This is the transaction fee you may discard if change is smaller than dust at this level</translation>
+ </message>
+ <message>
+ <source>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</source>
+ <translation>Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.</translation>
+ </message>
+ <message>
+ <source>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</source>
+ <translation>Unable to rewind the database to a pre-fork state. You will need to redownload the blockchain</translation>
+ </message>
+ <message>
+ <source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
+ <translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</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>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
+ </message>
+ <message>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation>-maxmempool must be at least %d MB</translation>
+ </message>
+ <message>
+ <source>Cannot resolve -%s address: '%s'</source>
+ <translation>Cannot resolve -%s address: '%s'</translation>
+ </message>
+ <message>
+ <source>Change index out of range</source>
+ <translation>Change index out of range</translation>
+ </message>
+ <message>
+ <source>Config setting for %s only applied on %s network when in [%s] section.</source>
+ <translation>Config setting for %s only applied on %s network when in [%s] section.</translation>
+ </message>
+ <message>
+ <source>Copyright (C) %i-%i</source>
+ <translation>Copyright (C) %i-%i</translation>
+ </message>
+ <message>
+ <source>Corrupted block database detected</source>
+ <translation>Corrupted block database detected</translation>
+ </message>
+ <message>
+ <source>Could not find asmap file %s</source>
+ <translation>Could not find asmap file %s</translation>
+ </message>
+ <message>
+ <source>Could not parse asmap file %s</source>
+ <translation>Could not parse asmap file %s</translation>
+ </message>
+ <message>
+ <source>Do you want to rebuild the block database now?</source>
+ <translation>Do you want to rebuild the block database now?</translation>
+ </message>
+ <message>
+ <source>Error initializing block database</source>
+ <translation>Error initializing block database</translation>
+ </message>
+ <message>
+ <source>Error initializing wallet database environment %s!</source>
+ <translation>Error initializing wallet database environment %s!</translation>
+ </message>
+ <message>
+ <source>Error loading %s</source>
+ <translation>Error loading %s</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Private keys can only be disabled during creation</source>
+ <translation>Error loading %s: Private keys can only be disabled during creation</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet corrupted</source>
+ <translation>Error loading %s: Wallet corrupted</translation>
+ </message>
+ <message>
+ <source>Error loading %s: Wallet requires newer version of %s</source>
+ <translation>Error loading %s: Wallet requires newer version of %s</translation>
+ </message>
+ <message>
+ <source>Error loading block database</source>
+ <translation>Error loading block database</translation>
+ </message>
+ <message>
+ <source>Error opening block database</source>
+ <translation>Error opening block database</translation>
+ </message>
+ <message>
+ <source>Failed to listen on any port. Use -listen=0 if you want this.</source>
+ <translation>Failed to listen on any port. Use -listen=0 if you want this.</translation>
+ </message>
+ <message>
+ <source>Failed to rescan the wallet during initialization</source>
+ <translation>Failed to rescan the wallet during initialization</translation>
+ </message>
+ <message>
+ <source>Importing...</source>
+ <translation>Importing...</translation>
+ </message>
+ <message>
+ <source>Incorrect or no genesis block found. Wrong datadir for network?</source>
+ <translation>Incorrect or no genesis block found. Wrong datadir for network?</translation>
+ </message>
+ <message>
+ <source>Initialization sanity check failed. %s is shutting down.</source>
+ <translation>Initialization sanity check failed. %s is shutting down.</translation>
+ </message>
+ <message>
+ <source>Invalid P2P permission: '%s'</source>
+ <translation>Invalid P2P permission: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -%s=&lt;amount&gt;: '%s'</source>
+ <translation>Invalid amount for -%s=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</source>
+ <translation>Invalid amount for -discardfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</source>
+ <translation>Invalid amount for -fallbackfee=&lt;amount&gt;: '%s'</translation>
+ </message>
+ <message>
+ <source>Specified blocks directory "%s" does not exist.</source>
+ <translation>Specified blocks directory "%s" does not exist.</translation>
+ </message>
+ <message>
+ <source>Unknown address type '%s'</source>
+ <translation>Unknown address type '%s'</translation>
+ </message>
+ <message>
+ <source>Unknown change type '%s'</source>
+ <translation>Unknown change type '%s'</translation>
+ </message>
+ <message>
+ <source>Upgrading txindex database</source>
+ <translation>Upgrading txindex database</translation>
+ </message>
+ <message>
+ <source>Loading P2P addresses...</source>
+ <translation>Loading P2P addresses...</translation>
+ </message>
+ <message>
+ <source>Loading banlist...</source>
+ <translation>Loading banlist...</translation>
+ </message>
+ <message>
+ <source>Not enough file descriptors available.</source>
+ <translation>Not enough file descriptors available.</translation>
+ </message>
+ <message>
+ <source>Prune cannot be configured with a negative value.</source>
+ <translation>Prune cannot be configured with a negative value.</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -txindex.</source>
+ <translation>Prune mode is incompatible with -txindex.</translation>
+ </message>
+ <message>
+ <source>Replaying blocks...</source>
+ <translation>Replaying blocks...</translation>
+ </message>
+ <message>
+ <source>Rewinding blocks...</source>
+ <translation>Rewinding blocks...</translation>
+ </message>
+ <message>
+ <source>The source code is available from %s.</source>
+ <translation>The source code is available from %s.</translation>
+ </message>
+ <message>
+ <source>Transaction fee and change calculation failed</source>
+ <translation>Transaction fee and change calculation failed</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer. %s is probably already running.</source>
+ <translation>Unable to bind to %s on this computer. %s is probably already running.</translation>
+ </message>
+ <message>
+ <source>Unable to generate keys</source>
+ <translation>Unable to generate keys</translation>
+ </message>
+ <message>
+ <source>Unsupported logging category %s=%s.</source>
+ <translation>Unsupported logging category %s=%s.</translation>
+ </message>
+ <message>
+ <source>Upgrading UTXO database</source>
+ <translation>Upgrading UTXO database</translation>
+ </message>
+ <message>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation>User Agent comment (%s) contains unsafe characters.</translation>
+ </message>
+ <message>
+ <source>Verifying blocks...</source>
+ <translation>Verifying blocks...</translation>
+ </message>
+ <message>
+ <source>Wallet needed to be rewritten: restart %s to complete</source>
+ <translation>Wallet needed to be rewritten: restart %s to complete</translation>
+ </message>
+ <message>
+ <source>Error: Listening for incoming connections failed (listen returned error %s)</source>
+ <translation>Error: Listening for incoming connections failed (listen returned error %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>Invalid amount for -maxtxfee=&lt;amount&gt;: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to send after the fee has been deducted</source>
+ <translation>The transaction amount is too small to send after the fee has been deducted</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>You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain</translation>
+ </message>
+ <message>
+ <source>Error reading from database, shutting down.</source>
+ <translation>Error reading from database, shutting down.</translation>
+ </message>
+ <message>
+ <source>Error upgrading chainstate database</source>
+ <translation>Error upgrading chainstate database</translation>
+ </message>
+ <message>
+ <source>Error: Disk space is low for %s</source>
+ <translation>Error: Disk space is low for %s</translation>
+ </message>
+ <message>
+ <source>Invalid -onion address or hostname: '%s'</source>
+ <translation>Invalid -onion address or hostname: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid -proxy address or hostname: '%s'</source>
+ <translation>Invalid -proxy address or hostname: '%s'</translation>
+ </message>
+ <message>
+ <source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
+ <translation>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</translation>
+ </message>
+ <message>
+ <source>Invalid netmask specified in -whitelist: '%s'</source>
+ <translation>Invalid netmask specified in -whitelist: '%s'</translation>
+ </message>
+ <message>
+ <source>Need to specify a port with -whitebind: '%s'</source>
+ <translation>Need to specify a port with -whitebind: '%s'</translation>
+ </message>
+ <message>
+ <source>Prune mode is incompatible with -blockfilterindex.</source>
+ <translation>Prune mode is incompatible with -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Reducing -maxconnections from %d to %d, because of system limitations.</source>
+ <translation>Reducing -maxconnections from %d to %d, because of system limitations.</translation>
+ </message>
+ <message>
+ <source>Section [%s] is not recognized.</source>
+ <translation>Section [%s] is not recognized.</translation>
+ </message>
+ <message>
+ <source>Signing transaction failed</source>
+ <translation>Signing transaction failed</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" does not exist</source>
+ <translation>Specified -walletdir "%s" does not exist</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is a relative path</source>
+ <translation>Specified -walletdir "%s" is a relative path</translation>
+ </message>
+ <message>
+ <source>Specified -walletdir "%s" is not a directory</source>
+ <translation>Specified -walletdir "%s" is not a directory</translation>
+ </message>
+ <message>
+ <source>The specified config file %s does not exist
+</source>
+ <translation>The specified config file %s does not exist
+</translation>
+ </message>
+ <message>
+ <source>The transaction amount is too small to pay the fee</source>
+ <translation>The transaction amount is too small to pay the fee</translation>
+ </message>
+ <message>
+ <source>This is experimental software.</source>
+ <translation>This is experimental software.</translation>
+ </message>
+ <message>
+ <source>Transaction amount too small</source>
+ <translation>Transaction amount too small</translation>
+ </message>
+ <message>
+ <source>Transaction too large</source>
+ <translation>Transaction too large</translation>
+ </message>
+ <message>
+ <source>Unable to bind to %s on this computer (bind returned error %s)</source>
+ <translation>Unable to bind to %s on this computer (bind returned error %s)</translation>
+ </message>
+ <message>
+ <source>Unable to create the PID file '%s': %s</source>
+ <translation>Unable to create the PID file '%s': %s</translation>
+ </message>
+ <message>
+ <source>Unable to generate initial keys</source>
+ <translation>Unable to generate initial keys</translation>
+ </message>
+ <message>
+ <source>Unknown -blockfilterindex value %s.</source>
+ <translation>Unknown -blockfilterindex value %s.</translation>
+ </message>
+ <message>
+ <source>Verifying wallet(s)...</source>
+ <translation>Verifying wallet(s)...</translation>
+ </message>
+ <message>
+ <source>Warning: unknown new rules activated (versionbit %i)</source>
+ <translation>Warning: unknown new rules activated (versionbit %i)</translation>
+ </message>
+ <message>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you may pay when fee estimates are not available.</source>
+ <translation>This is the transaction fee you may pay when fee estimates are not available.</translation>
+ </message>
+ <message>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
+ </message>
+ <message>
+ <source>%s is set very high!</source>
+ <translation>%s is set very high!</translation>
+ </message>
+ <message>
+ <source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
+ <translation>Error loading wallet %s. Duplicate -wallet filename specified.</translation>
+ </message>
+ <message>
+ <source>Starting network threads...</source>
+ <translation>Starting network threads...</translation>
+ </message>
+ <message>
+ <source>The wallet will avoid paying less than the minimum relay fee.</source>
+ <translation>The wallet will avoid paying less than the minimum relay fee.</translation>
+ </message>
+ <message>
+ <source>This is the minimum transaction fee you pay on every transaction.</source>
+ <translation>This is the minimum transaction fee you pay on every transaction.</translation>
+ </message>
+ <message>
+ <source>This is the transaction fee you will pay if you send a transaction.</source>
+ <translation>This is the transaction fee you will pay if you send a transaction.</translation>
+ </message>
+ <message>
+ <source>Transaction amounts must not be negative</source>
+ <translation>Transaction amounts must not be negative</translation>
+ </message>
+ <message>
+ <source>Transaction has too long of a mempool chain</source>
+ <translation>Transaction has too long of a mempool chain</translation>
+ </message>
+ <message>
+ <source>Transaction must have at least one recipient</source>
+ <translation>Transaction must have at least one recipient</translation>
+ </message>
+ <message>
+ <source>Unknown network specified in -onlynet: '%s'</source>
+ <translation>Unknown network specified in -onlynet: '%s'</translation>
+ </message>
+ <message>
+ <source>Insufficient funds</source>
+ <translation>Insufficient funds</translation>
+ </message>
+ <message>
+ <source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
+ <translation>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</translation>
+ </message>
+ <message>
+ <source>Warning: Private keys detected in wallet {%s} with disabled private keys</source>
+ <translation>Warning: Private keys detected in wallet {%s} with disabled private keys</translation>
+ </message>
+ <message>
+ <source>Cannot write to data directory '%s'; check permissions.</source>
+ <translation>Cannot write to data directory '%s'; check permissions.</translation>
+ </message>
+ <message>
+ <source>Loading block index...</source>
+ <translation>Loading block index...</translation>
+ </message>
+ <message>
<source>Loading wallet...</source>
<translation>Sedang baca wallet...</translation>
</message>
<message>
+ <source>Cannot downgrade wallet</source>
+ <translation>Cannot downgrade wallet</translation>
+ </message>
+ <message>
+ <source>Rescanning...</source>
+ <translation>Rescanning...</translation>
+ </message>
+ <message>
<source>Done loading</source>
<translation>Baca Selesai</translation>
</message>
diff --git a/src/qt/locale/bitcoin_my.ts b/src/qt/locale/bitcoin_my.ts
index ec03afa3b7..71fd243c24 100644
--- a/src/qt/locale/bitcoin_my.ts
+++ b/src/qt/locale/bitcoin_my.ts
@@ -107,6 +107,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -179,6 +182,10 @@
<source>Export the data in the current tab to a file</source>
<translation>လက်ရှိ tab မှာရှိတဲ့ဒေတာတွေကို ဖိုင်လ်မှာသိမ်းမယ်။</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>အမှား</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_nb.ts b/src/qt/locale/bitcoin_nb.ts
index f24c1aa3b6..82c74c3107 100644
--- a/src/qt/locale/bitcoin_nb.ts
+++ b/src/qt/locale/bitcoin_nb.ts
@@ -70,10 +70,6 @@
<translation>Dette er dine Bitcoin adresser for å sende å sende betalinger. Husk å sjekke beløp og mottager adresser før du sender mynter.</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.</source>
- <translation>Dette er dine Bitcoin adresse for å betalinger. Det er anbefalt å bruke en my mottager adresse for hver transakjon.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopier adresse</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Lommeboken er &lt;b&gt;kryptert&lt;/b&gt; og for tiden &lt;b&gt;låst&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>En fatal feil har inntruffet. Bitcoin kan ikke lenger trygt fortsette, og må derfor avslutte.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1135,10 +1127,6 @@
<translation>Viser hvorvidt angitt SOCKS5-mellomtjener blir brukt for å nå noder via denne nettverkstypen.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Bruk egen SOCKS&amp;5-proxy for å nå noder via Tor hidden services:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Skjul ikonet fra systemkurven.</translation>
</message>
@@ -1271,10 +1259,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Koble til Bitcoin-nettverket gjennom en separat SOCKS5 mellomtjener for Tor skjulte tjenester.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Vindu</translation>
</message>
@@ -1449,7 +1433,22 @@
<source>Current total balance in watch-only addresses</source>
<translation>Nåværende totale balanse i kun observerbare adresser</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Totalbeløp</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>eller</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1701,10 +1700,6 @@
<translation>Blokkjeden</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Nåværende antall blokker</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Hukommelsespulje</translation>
</message>
@@ -1749,10 +1744,6 @@
<translation>Velg en node for å vise detaljert informasjon.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Hvitelistet</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Retning</translation>
</message>
@@ -1805,10 +1796,6 @@
<translation>Tjenester</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban Poengsum</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Tilkoblingstid</translation>
</message>
@@ -1957,14 +1944,6 @@
<translation>Utgående</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nei</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Ukjent</translation>
</message>
@@ -2063,12 +2042,28 @@
<source>Copy amount</source>
<translation>Kopier beløp</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Kunne ikke låse opp lommebok.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-kode</translation>
+ <source>Amount:</source>
+ <translation>Beløp:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Merkelapp:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Melding:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Lommebok:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2090,30 +2085,6 @@
<source>Payment information</source>
<translation>Betalingsinformasjon</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresse</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Beløp</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Beskrivelse</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Melding</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Lommebok</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2385,18 +2356,10 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Bekreft transaksjonsforslaget</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Kopier PSBT til utklippstavlen</translation>
- </message>
- <message>
<source>Send</source>
<translation>Send</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT kopiert</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Kun-observer balanse:</translation>
</message>
@@ -3174,12 +3137,12 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Å lukke lommeboken for lenge kan føre til at du må synkronisere hele kjeden hvis beskjæring er aktivert.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Ingen lommebok har blitt lastet inn.</translation>
+ <source>Create a new wallet</source>
+ <translation>Lag en ny lommebok</translation>
</message>
</context>
<context>
@@ -3252,6 +3215,10 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Eksporter data i den valgte fliken til en fil</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Feilmelding</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Sikkerhetskopier lommebok</translation>
</message>
@@ -3295,10 +3262,6 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Beskjæring: siste lommeboksynkronisering går utenfor beskjærte data. Du må bruke -reindex (laster ned hele blokkjeden igjen for beskjærte noder)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Feil: En fatal intern feil oppstod, se debug.log for detaljer</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Beskjærer blokklageret...</translation>
</message>
@@ -3311,10 +3274,6 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>%s-utviklerne</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Kan ikke generere en ledelse-nøkkel. Ingen taster i den interne tasten og kan ikke generere noen nøkler.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan ikke låse datamappen %s. %s kjører antagelig allerede.</translation>
</message>
@@ -3363,14 +3322,6 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Advarsel: Vi ser ikke ut til å være i full overenstemmelse med våre likemenn! Du kan trenge å oppgradere, eller andre noder kan trenge å oppgradere.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d av minst 100 blokker har uventet versjon</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s skadet, berging mislyktes</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool må være minst %d MB</translation>
</message>
@@ -3471,10 +3422,6 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Laster maskin-til-maskin -adresser…</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Feil: For lite diskplass!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Laster inn bannlysningsliste…</translation>
</message>
@@ -3645,10 +3592,6 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Advarsel: Ukjente nye regler aktivert (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zapper alle transaksjoner fra lommeboken...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee er satt veldig høyt! Så stort gebyr kan bli betalt ved en enkelt transaksjon.</translation>
</message>
@@ -3661,10 +3604,6 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Total lengde av nettverks-versionstreng (%i) er over maks lengde (%i). Reduser tallet eller størrelsen av uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Advarsel: Lommeboksfil skadet, data berget! Original %s lagret som %s i %s; hvis din saldo eller transaksjoner er uriktige, bør du gjenopprette fra sikkerhetskopi.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s er satt veldig høyt!</translation>
</message>
@@ -3709,10 +3648,6 @@ Merk: Siden avgiften er beregnet per byte-basis, vil et gebyr på "100 satoshis
<translation>Utilstrekkelige midler</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Kan ikke oppgradere en delt lommebok uten HD uten å oppgradere til støtte for forhåndsdelt tastatur. Bruk -upgradewallet = 169900 eller -upgradewallet uten versjon spesifisert.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Avgiftsberegning mislyktes. Fallbackfee er deaktivert. Vent et par blokker eller aktiver -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ne.ts b/src/qt/locale/bitcoin_ne.ts
index 7f74cb5d50..c7cb8d2730 100644
--- a/src/qt/locale/bitcoin_ne.ts
+++ b/src/qt/locale/bitcoin_ne.ts
@@ -273,7 +273,10 @@
<source>Current total balance in watch-only addresses</source>
<translation>हेर्ने-मात्र ठेगानामा रहेको हालको जम्मा ब्यालेन्स</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
<context>
<name>PaymentServer</name>
</context>
@@ -318,10 +321,6 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Amount</source>
- <translation>रकम</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -443,10 +442,6 @@
<translation>चेतावनी: हामी हाम्रा सहकर्मीहरूसँग पूर्णतया सहमत छैनौं जस्तो देखिन्छ! तपाईंले अपग्रेड गर्नु पर्ने हुनसक्छ वा अरू नोडहरूले अपग्रेड गर्नु पर्ने हुनसक्छ ।</translation>
</message>
<message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s मा क्षति, बचाव विफल भयो</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool कम्तिमा %d MB को हुनुपर्छ ।</translation>
</message>
diff --git a/src/qt/locale/bitcoin_nl.ts b/src/qt/locale/bitcoin_nl.ts
index ad713a8cc8..2cb42a0e39 100644
--- a/src/qt/locale/bitcoin_nl.ts
+++ b/src/qt/locale/bitcoin_nl.ts
@@ -15,7 +15,7 @@
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>Kopieer het geselecteerde adres naar het klembord</translation>
+ <translation>Kopieer het momenteel geselecteerde adres naar het systeem klembord</translation>
</message>
<message>
<source>&amp;Copy</source>
@@ -47,7 +47,7 @@
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>Kies het adres om munten naar te versturen</translation>
+ <translation>Kies het adres om de munten naar te versturen</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
@@ -70,8 +70,10 @@
<translation>Dit zijn uw Bitcoinadressen om betalingen mee te verzenden. Controleer altijd het bedrag en het ontvangstadres voordat u uw bitcoins verzendt.</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.</source>
- <translation>Dit zijn jouw Bitcoin adressen voor het ontvangen van betalingen. Gebruik de 'Nieuwe ontvangst adres maken' knop in de ontvangst tab om een nieuwe adres te maken.</translation>
+ <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>Dit zijn uw Bitcoin adressen voor het ontvangen van betalingen. Gebruik de 'Nieuw ontvangst adres maken' knop in de ontvangst tab om een nieuwe adres te maken.
+Ondertekenen is alleen mogelijk met adressen van het type 'legacy'.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>Bijgewerkt</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Laad PSBT van bestand...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Laad gedeeltelijk ondertekende Bitcoin-transactie</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Laad PSBT van klembord</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Laad gedeeltelijk ondertekende Bitcoin-transactie vanaf het klembord</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Nodevenster</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Portemonnee Sluiten</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Sluit Alle Portemonnees...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Sluit alle portemonnees</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Toon het %1 hulpbericht om een lijst te krijgen met mogelijke Bitcoin commandoregelopties</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Maskeer waarden</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Maskeer de waarden op het tabblad Overzicht</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>standaard portemonnee</translation>
</message>
@@ -630,8 +664,12 @@
<translation>Portemonnee is &lt;b&gt;versleuteld&lt;/b&gt; en momenteel &lt;b&gt;gesloten&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Een fatale fout heeft zich voorgedaan. Bitcoin kan niet veilig worden verdergezet en wordt afgesloten.</translation>
+ <source>Original message:</source>
+ <translation>Origineel bericht:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Er is een fatale fout opgetreden. %1 kan niet langer veilig doorgaan en wordt afgesloten.</translation>
</message>
</context>
<context>
@@ -836,6 +874,14 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Maak een lege portemonnee</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Gebruik descriptors voor scriptPubKey-beheer</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Descriptor Portemonnee</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Creëer</translation>
</message>
@@ -1140,10 +1186,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Toont aan of de aangeleverde standaard SOCKS5 proxy gebruikt wordt om peers te bereiken via dit netwerktype.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Gebruik aparte SOCKS&amp;5-proxy om peers te bereiken via verborgen Tor-diensten:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Verberg het icoon van de systeembalk.</translation>
</message>
@@ -1276,10 +1318,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Maak verbinding met Bitcoinnetwerk door een aparte SOCKS5-proxy voor verborgen diensten van Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Scherm</translation>
</message>
@@ -1320,6 +1358,14 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Munt controle functies weergeven of niet.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Maak verbinding met het Bitcoin-netwerk via een aparte SOCKS5-proxy voor Tor Onion-services.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Gebruik afzonderlijke SOCKS &amp; 5-proxy om peers te bereiken via Tor Onion-services:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>Transactie-URL's van &amp;derden</translation>
</message>
@@ -1454,8 +1500,59 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<source>Current total balance in watch-only addresses</source>
<translation>Huidige balans in alleen-bekijkbare adressen.</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Privacymodus geactiveerd voor het tabblad Overzicht. Om de waarden te ontmaskeren, schakelt u Instellingen -&gt; Maskeer waarden uit.</translation>
+ </message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialoog</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Signeer Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Zend Tx uit</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Kopieer naar klembord</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Opslaan...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Sluiten</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Laden transactie niet gelukt: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Tekenen transactie niet gelukt: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Kon geen inputs meer ondertekenen.</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Totaalbedrag</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>of</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1718,10 +1815,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Blokketen</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Huidig aantal blokken</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Geheugenpoel</translation>
</message>
@@ -1766,10 +1859,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Selecteer een peer om gedetailleerde informatie te bekijken.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Toegestaan</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Directie</translation>
</message>
@@ -1822,10 +1911,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Diensten</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ban score</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Connectie tijd</translation>
</message>
@@ -1974,14 +2059,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<translation>Uitgaand</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nee</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Onbekend</translation>
</message>
@@ -2080,12 +2157,28 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<source>Copy amount</source>
<translation>Kopieer bedrag</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Kon de portemonnee niet openen.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-code</translation>
+ <source>Amount:</source>
+ <translation>Bedrag:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Label:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Bericht:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Portemonnee:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2107,30 +2200,6 @@ Dit is ideaal voor alleen-lezen portommonees.</translation>
<source>Payment information</source>
<translation>Betalingsinformatie</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adres</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Bedrag</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Label</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Bericht</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portemonnee</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2378,10 +2447,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Weet u zeker dat u wilt verzenden?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Gelieve je transactie-voorstel te controleren. Dit zal een Partially Signed Bitcoin Transaction (PSBT) maken die je kan kopiëren en dan tekenen met b.v. een offline %1 wallet, of een PSBT-compatibele hardware wallet.</translation>
- </message>
- <message>
<source>or</source>
<translation>of</translation>
</message>
@@ -2418,18 +2483,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Bevestig transactievoorstel</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Kopieer PSBT naar klembord</translation>
- </message>
- <message>
<source>Send</source>
<translation>Verstuur</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT is gekopieerd</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Alleen-lezen balans:</translation>
</message>
@@ -3211,12 +3268,16 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>De portemonee te lang gesloten houden kan leiden tot het moeten hersynchroniseren van de hele keten als snoeien aktief is.</translation>
</message>
-</context>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Sluit alle portemonnees</translation>
+ </message>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Er is geen portemonnee geladen.</translation>
+ <source>Create a new wallet</source>
+ <translation>Nieuwe wallet creëren</translation>
</message>
</context>
<context>
@@ -3289,6 +3350,10 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Exporteer de data in de huidige tab naar een bestand</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Fout</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Portemonnee backuppen</translation>
</message>
@@ -3332,10 +3397,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Prune: laatste wallet synchronisatie gaat verder terug dan de middels -prune beperkte data. U moet -reindex gebruiken (downloadt opnieuw de gehele blokketen voor een pruned node)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Fout: er is een fout opgetreden, zie debug.log voor details</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Blokopslag prunen...</translation>
</message>
@@ -3348,10 +3409,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>De %s ontwikkelaars</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Kan geen rest-adres sleutel genereren. Er zijn geen sleutels in de interne sleutelverzameling en ik kan geen sleutels genereren.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan geen lock verkrijgen op gegevensmap %s. %s draait waarschijnlijk al.</translation>
</message>
@@ -3400,14 +3457,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Waarschuwing: Het lijkt erop dat we geen consensus kunnen vinden met onze peers! Mogelijk dient u te upgraden, of andere nodes moeten wellicht upgraden.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d van de laatste 100 blokken hebben een onverwachte versie</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupt, veiligstellen mislukt</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool moet minstens %d MB zijn</translation>
</message>
@@ -3532,10 +3581,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>P2P-adressen aan het laden...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Error: Opslagruimte te weinig!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Verbanningslijst aan het laden...</translation>
</message>
@@ -3718,10 +3763,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Waarschuwing: onbekende nieuwe regels geactiveerd (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Bezig met het zappen van alle transacties van de portemonnee...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee staat zeer hoog! Transactiekosten van deze grootte kunnen worden gebruikt in een enkele transactie.</translation>
</message>
@@ -3734,10 +3775,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Totale lengte van netwerkversiestring (%i) overschrijdt maximale lengte (%i). Verminder het aantal of grootte van uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Waarschuwing: portemonnee bestand is corrupt, data is veiliggesteld! Originele %s is opgeslagen als %s in %s; als uw balans of transacties incorrect zijn dient u een backup terug te zetten.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is zeer hoog ingesteld!</translation>
</message>
@@ -3782,10 +3819,6 @@ Notitie: Omdat de vergoeding per byte wordt gerekend, zal een vergoeding van "10
<translation>Ontoereikend saldo</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Het is niet mogelijk een non HD split portemonnee te upgraden zonder pre split keypool te ondersteunen. Gebruik -upgradewallet=169900 of -upgradewallet zonder een specifiek versie nummer.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Het inschatten van de vergoeding is gefaald. Fallbackfee is uitgeschakeld. Wacht een aantal blocks of schakel -fallbackfee in.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pam.ts b/src/qt/locale/bitcoin_pam.ts
index 585fa22226..e747fcc5af 100644
--- a/src/qt/locale/bitcoin_pam.ts
+++ b/src/qt/locale/bitcoin_pam.ts
@@ -341,11 +341,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Maka-&lt;b&gt;encrypt&lt;/b&gt; ya ing wallet at kasalukuyan yang maka-&lt;b&gt;locked&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Atin kamalian a milyari. Ali ne magsilbing sumulung pa ing Bitcoin at kailangan na ng tuknang.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -595,6 +591,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -649,10 +648,6 @@
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Kasalungsungan bilang dareng blocks</translation>
- </message>
- <message>
<source>Last block time</source>
<translation>Tatauling oras na ning block</translation>
</message>
@@ -691,34 +686,26 @@
<source>Copy amount</source>
<translation>Kopyan ing alaga</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Kopyan ing address</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Address</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Alaga</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>Ali ya bisang mag-unlock ing wallet</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Label</source>
- <translation>Label</translation>
+ <source>Amount:</source>
+ <translation>Alaga:</translation>
</message>
<message>
- <source>Message</source>
- <translation>Mensayi</translation>
+ <source>Message:</source>
+ <translation>Mensayi:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Wallet</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Kopyan ing address</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1279,6 +1266,10 @@
</context>
<context>
<name>WalletView</name>
+ <message>
+ <source>Error</source>
+ <translation>Mali</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_pl.ts b/src/qt/locale/bitcoin_pl.ts
index 552d3e1ca7..1d8d1f89ff 100644
--- a/src/qt/locale/bitcoin_pl.ts
+++ b/src/qt/locale/bitcoin_pl.ts
@@ -67,11 +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>Tutaj znajdują się adresy Bitcoin na które wysyłasz płatności. Zawsze sprawdzaj ilość i adres odbiorcy przed wysyłką monet.</translation>
+ <translation>To są twoje adresy Bitcoin do wysyłania płatności. Zawsze sprawdź kwotę i adres odbiorcy przed wysłaniem monet.</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.</source>
- <translation>To są Twoje adresy Bitcoin do otrzymywania płatności. Użyj przycisku "Stwórz nowy adres odbiorczy" w zakładce odbioru żeby stworzyć nowy adres.</translation>
+ <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>To są twoje adresy Bitcoin do otrzymywania płatności. Użyj przycisku „Utwórz nowy adres odbiorcy” na karcie odbioru, aby utworzyć nowe adresy.
+Podpisywanie jest możliwe tylko z adresami typu „legacy”.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -323,7 +325,7 @@
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>Otwórz URI...</translation>
+ <translation>Otwórz &amp;URI...</translation>
</message>
<message>
<source>Create Wallet...</source>
@@ -482,6 +484,22 @@
<translation>Aktualny</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>Wczytaj PSBT z p&amp;liku ..</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Załaduj częściowo podpisaną transakcję Bitcoin</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Wczytaj PSBT do schowka</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Załaduj częściowo podpisaną transakcję Bitcoin ze schowka</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Okno węzła</translation>
</message>
@@ -518,6 +536,14 @@
<translation>Zamknij portfel</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Zamknij wszystkie portfele ...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Zamknij wszystkie portfele</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Pokaż pomoc %1 aby zobaczyć listę wszystkich opcji lnii poleceń.</translation>
</message>
@@ -630,10 +656,10 @@
<translation>Portfel jest &lt;b&gt;zaszyfrowany&lt;/b&gt; i obecnie &lt;b&gt;zablokowany&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Wystąpił krytyczny błąd. Bitcoin nie jest w stanie kontynuować bezpiecznie i zostanie zamknięty.</translation>
+ <source>Original message:</source>
+ <translation>Wiadomość oryginalna:</translation>
</message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -835,6 +861,10 @@
<translation>Stwórz czysty portfel</translation>
</message>
<message>
+ <source>Descriptor Wallet</source>
+ <translation>Portfel deskryptora</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Stwórz</translation>
</message>
@@ -1139,10 +1169,6 @@
<translation>Pakazuje czy dostarczone domyślne SOCKS5 proxy jest użyte do połączenia z węzłami przez sieć tego typu.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Użyj oddzielnego proxy SOCKS&amp;5 aby osiągnąć węzły w ukrytych usługach Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Ukryj ikonę z zasobnika systemowego.</translation>
</message>
@@ -1275,10 +1301,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Połącz się z siecią Bitcoin przy pomocy oddzielnego SOCKS5 proxy dla sieci TOR</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Okno</translation>
</message>
@@ -1453,7 +1475,78 @@
<source>Current total balance in watch-only addresses</source>
<translation>Łączna kwota na podglądanych adresach</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Kopiuj do schowka</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Zapisz ...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Zamknij</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Nie udało się wczytać transakcji: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Nie udało się podpisać transakcji: %1</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>transakcja</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Nieznany błąd podczas przetwarzania transakcji.</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT skopiowane do schowka</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Zapisz dane transakcji</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT zapisane na dysk.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>Wysyłanie %1 do %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Nie można obliczyć opłaty za transakcję lub łącznej kwoty transakcji.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Opłata transakcyjna:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Łączna wartość</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>lub</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Transakcja ciągle oczekuje na podpis(y).</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1810,6 @@
<translation>Łańcuch bloków</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Aktualna liczba bloków</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Memory Pool (obszar pamięci)</translation>
</message>
@@ -1765,10 +1854,6 @@
<translation>Wybierz węzeł żeby zobaczyć szczegóły.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Biała lista</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Kierunek</translation>
</message>
@@ -1817,12 +1902,12 @@
<translation>Zwiększ rozmiar czcionki</translation>
</message>
<message>
- <source>Services</source>
- <translation>Usługi</translation>
+ <source>Permissions</source>
+ <translation>Uprawnienia</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Punkty karne</translation>
+ <source>Services</source>
+ <translation>Usługi</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2058,6 @@
<translation>Wyjściowy</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Tak</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nie</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Nieznany</translation>
</message>
@@ -2079,56 +2156,56 @@
<source>Copy amount</source>
<translation>Kopiuj kwotę</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Kod QR</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>Nie można było odblokować portfela.</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;URI</source>
- <translation>Kopiuj &amp;URI</translation>
+ <source>Request payment to ...</source>
+ <translation>Żądaj płatności od ...</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Kopiuj &amp;adres</translation>
+ <source>Address:</source>
+ <translation>Adres:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Zapisz obraz...</translation>
+ <source>Amount:</source>
+ <translation>Kwota:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Zażądaj płatności do %1</translation>
+ <source>Label:</source>
+ <translation>Etykieta:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Informacje o płatności</translation>
+ <source>Message:</source>
+ <translation>Wiadomość:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Portfel:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Adres</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Kopiuj &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Kwota</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Kopiuj &amp;adres</translation>
</message>
<message>
- <source>Label</source>
- <translation>Etykieta</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Zapisz obraz...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Wiadomość</translation>
+ <source>Request payment to %1</source>
+ <translation>Zażądaj płatności do %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Portfel</translation>
+ <source>Payment information</source>
+ <translation>Informacje o płatności</translation>
</message>
</context>
<context>
@@ -2378,8 +2455,16 @@ Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za
<translation>Czy na pewno chcesz wysłać?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>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>
+ <source>Create Unsigned</source>
+ <translation>Utwórz niepodpisaną transakcję</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Zapisz dane transakcji</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>Zapisano PSBT</translation>
</message>
<message>
<source>or</source>
@@ -2418,18 +2503,10 @@ Uwaga: Ponieważ opłata jest naliczana za każdy bajt, opłata "100 satoshi za
<translation>Potwierdź propozycję transakcji</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Skopiuj PSBT do schowka</translation>
- </message>
- <message>
<source>Send</source>
<translation>Wyślij</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>Skopiowano PSBT</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Kwota na obserwowanych kontach:</translation>
</message>
@@ -3210,14 +3287,22 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
</message>
<message>
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
- <translation>Zamknięcie portfela na zbyt długo może skutkować konieczność ponownego załadowania całego łańcucha, jeżeli jest włączony pruning.</translation>
+ <translation>Zamknięcie portfela na zbyt długo może skutkować koniecznością ponownego załadowania całego łańcucha, jeżeli jest włączony pruning.</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Zamknij wszystkie portfele</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Na pewno zamknąć wszystkie portfe?</translation>
</message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nie załadowano żadnego portfela.</translation>
+ <source>Create a new wallet</source>
+ <translation>Stwórz nowy portfel</translation>
</message>
</context>
<context>
@@ -3290,6 +3375,22 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Eksportuj dane z aktywnej karty do pliku</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Błąd</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Wczytaj dane transakcji</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PSBT musi być mniejsze niż 100MB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Nie można odczytać PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Kopia zapasowa portfela</translation>
</message>
@@ -3333,10 +3434,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Prune: ostatnia synchronizacja portfela jest za danymi. Muszisz -reindexować (pobrać cały ciąg bloków ponownie w przypadku przyciętego węzła)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Błąd: Wystąpił fatalny błąd wewnętrzny, sprawdź szczegóły w debug.log</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Przycinanie zapisu bloków...</translation>
</message>
@@ -3349,10 +3446,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Deweloperzy %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Nie mogę wygenerować adresu reszty. Brak kluczy w wewnętrznym magazynie kluczy i nie można wygenerować żadnych kluczy.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Nie można uzyskać blokady na katalogu z danymi %s. %s najprawdopodobniej jest już uruchomiony.</translation>
</message>
@@ -3401,14 +3494,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Uwaga: Wygląda na to, że nie ma pełnej zgodności z naszymi węzłami! Możliwe, że potrzebujesz aktualizacji bądź inne węzły jej potrzebują</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d z ostatnich 100 bloków ma nieoczekiwaną wersję</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s uszkodzony, odtworzenie się nie powiodło</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool musi być przynajmniej %d MB</translation>
</message>
@@ -3485,6 +3570,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nie udało się ponownie przeskanować portfela podczas inicjalizacji.</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Nie udało się zweryfikować bazy danych</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importowanie…</translation>
</message>
@@ -3513,6 +3602,30 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Nieprawidłowa kwota dla -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase: nie powiodło się wykonanie instrukcji weryfikującej bazę danych: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: nie udało się pobrać wersji schematu portfela sqlite: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: nie udało się pobrać identyfikatora aplikacji: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase: nie udało się przygotować instrukcji do weryfikacji bazy danych: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase: nie udało się odczytać błędu weryfikacji bazy danych: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase: nieoczekiwany identyfikator aplikacji. Oczekiwano %u, otrzymano %u</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>Podany folder bloków "%s" nie istnieje.
</translation>
@@ -3534,10 +3647,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Wczytywanie adresów P2P...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Błąd: Zbyt mało miejsca na dysku!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Ładowanie listy zablokowanych...</translation>
</message>
@@ -3614,6 +3723,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Musisz przebudować bazę używając parametru -reindex aby wrócić do trybu pełnego. To spowoduje ponowne pobranie całego łańcucha bloków</translation>
</message>
<message>
+ <source>Disk space is too low!</source>
+ <translation>Zbyt mało miejsca na dysku!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Błąd odczytu z bazy danych, wyłączam się.</translation>
</message>
@@ -3626,6 +3739,10 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Błąd: zbyt mało miejsca na dysku dla %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Błąd: Pula kluczy jest pusta, odwołaj się do puli kluczy.</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Niewłaściwy adres -onion lub nazwa hosta: '%s'</translation>
</message>
@@ -3720,10 +3837,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Ostrzeżenie: aktywowano nieznane nowe reguły (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Usuwam wszystkie transakcje z portfela...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee ma ustawioną badzo dużą wartość! Tak wysokie opłaty mogą być zapłacone w jednej transakcji.</translation>
</message>
@@ -3736,10 +3849,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Całkowita długość łańcucha wersji (%i) przekracza maksymalną dopuszczalną długość (%i). Zmniejsz ilość lub rozmiar parametru uacomment.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Ostrzeżenie: Odtworzono dane z uszkodzonego pliku portfela! Oryginalny %s został zapisany jako %s w %s; jeśli twoje saldo lub transakcje są niepoprawne powinieneś odtworzyć kopię zapasową.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s jest ustawione bardzo wysoko!</translation>
</message>
@@ -3784,10 +3893,6 @@ Zwróć uwagę, że poprawnie zweryfikowana wiadomość potwierdza to, że nadaw
<translation>Niewystarczające środki</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Nie można zaktualizować portfela rozdzielnego bez HD, bez aktualizacji obsługi podzielonej bazy kluczy. Użyj -upgradewallet = 169900 lub -upgradewallet bez określonej wersji.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Estymacja opłat nieudana. Domyślna opłata jest wyłączona. Poczekaj kilka bloków lub włącz -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt.ts b/src/qt/locale/bitcoin_pt.ts
index 4df412cfad..4fbdadd059 100644
--- a/src/qt/locale/bitcoin_pt.ts
+++ b/src/qt/locale/bitcoin_pt.ts
@@ -70,10 +70,6 @@
<translation>Estes são os seus endereços Bitcoin para enviar pagamentos. Verifique sempre o valor e o endereço de receção antes de enviar moedas.</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.</source>
- <translation>Estes são os endereços Bitcoin para receiver pagamentos. Use o botão "Criar novo endereço para receiver" para crier novo endereço.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Copiar Endereço</translation>
</message>
@@ -482,6 +478,18 @@
<translation>Atualizado</translation>
</message>
<message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Carregar transação de Bitcoin parcialmente assinada</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Carregar PSBT da área de transferência...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Carregar transação de Bitcoin parcialmente assinada da área de transferência.</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Janela do nó</translation>
</message>
@@ -518,6 +526,14 @@
<translation>Fechar a carteira</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Fechar todas carteiras...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Fechar todas carteiras.</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Mostrar a mensagem de ajuda %1 para obter uma lista com possíveis opções a usar na linha de comandos.</translation>
</message>
@@ -630,10 +646,10 @@
<translation>A carteira está &lt;b&gt;encriptada&lt;/b&gt; e atualmente &lt;b&gt;bloqueada&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Ocorreu um erro fatal. O Bitcoin não pode continuar com segurança e irá fechar.</translation>
+ <source>Original message:</source>
+ <translation>Mensagem original:</translation>
</message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1078,7 +1094,7 @@
<name>OpenURIDialog</name>
<message>
<source>Open bitcoin URI</source>
- <translation>Abrir um bitcoin URI</translation>
+ <translation>Abrir um Bitcoin URI</translation>
</message>
<message>
<source>URI:</source>
@@ -1139,10 +1155,6 @@
<translation>Mostra se o padrão fornecido SOCKS5 proxy, está a ser utilizado para alcançar utilizadores participantes através deste tipo de rede.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Utilize um proxy SOCKS&amp;5 separado para alcançar utilizadores participantes através dos serviços ocultos do Tor.</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Esconder o ícone da barra de ferramentas.</translation>
</message>
@@ -1276,10 +1288,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Ligar à rede Bitcoin através de um proxy SOCKS5 separado para utilizar os serviços ocultos do Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Janela</translation>
</message>
@@ -1454,6 +1462,130 @@
<source>Current total balance in watch-only addresses</source>
<translation>Saldo disponível em endereços de apenas vigiar</translation>
</message>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Diálogo</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Assinar transação</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Transmitir transação</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Copiar para área de transferência</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Salvar...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Fechar</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Falha ao carregar transação: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Falha ao assinar transação: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Não pode assinar mais nenhuma entrada.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Assinadas entradas %1, mas mais assinaturas ainda são necessárias.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Transação assinada com sucesso. Transação está pronta para ser transmitida.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Erro desconhecido ao processar a transação.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Transação transmitida com sucesso.
+ID transação: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Falha ao transmitir a transação: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT copiada para a área de transferência.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Salvar informação de transação</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transação assinada parcialmente (binária) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT salva no disco.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>Envia %1 para %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Incapaz de calcular a taxa de transação ou o valor total da transação.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Paga taxa de transação:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Valor Total</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ou</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Transação tem %1 entradas não assinadas.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Transação está com alguma informação faltando sobre as entradas.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Transação continua precisando de assinatura(s).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Porém esta carteira não pode assinar transações.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Porém esta carteira não tem as chaves corretas.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Transação está completamente assinada e pronta para ser transmitida.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Status da transação é desconhecido.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1620,6 +1752,10 @@
<translation>Erro: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Erro ao inicializar configurações: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 ainda não foi fechado em segurança...</translation>
</message>
@@ -1718,10 +1854,6 @@
<translation>Cadeia de blocos</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Número atual de blocos</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Banco de Memória</translation>
</message>
@@ -1766,10 +1898,6 @@
<translation>Selecione um ponto para ver informação detalhada.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Permitido por si</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direção</translation>
</message>
@@ -1818,12 +1946,12 @@
<translation>Aumentar tamanho da letra</translation>
</message>
<message>
- <source>Services</source>
- <translation>Serviços</translation>
+ <source>Permissions</source>
+ <translation>Permissões</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Pontuação de Banimento</translation>
+ <source>Services</source>
+ <translation>Serviços</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1974,14 +2102,6 @@
<translation>Saída</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Sim</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Não</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Desconhecido</translation>
</message>
@@ -2080,56 +2200,60 @@
<source>Copy amount</source>
<translation>Copiar valor</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Não foi possível desbloquear a carteira.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Não foi possível gerar um novo endereço %1</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Código QR</translation>
+ <source>Request payment to ...</source>
+ <translation>Requisitar pagamento para ...</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>Copiar &amp;URI</translation>
+ <source>Address:</source>
+ <translation>Endereço:</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Copi&amp;ar Endereço</translation>
- </message>
- <message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Guardar Imagem...</translation>
+ <source>Amount:</source>
+ <translation>Valor:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Requisitar Pagamento para %1</translation>
+ <source>Label:</source>
+ <translation>Legenda:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Informação de Pagamento</translation>
+ <source>Message:</source>
+ <translation>Mensagem:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Carteira:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Endereço</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copiar &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Valor</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Copi&amp;ar Endereço</translation>
</message>
<message>
- <source>Label</source>
- <translation>Etiqueta</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Guardar Imagem...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Mensagem</translation>
+ <source>Request payment to %1</source>
+ <translation>Requisitar Pagamento para %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Carteira</translation>
+ <source>Payment information</source>
+ <translation>Informação de Pagamento</translation>
</message>
</context>
<context>
@@ -2378,8 +2502,20 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Tem a certeza que deseja enviar?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Por favor, reveja sua proposta de transação. Isto irá produzir uma transação de Bitcoin parcialmente assinada (PSBT)(sigla em inglês) a qual você pode copiar e então assinar com por exemplo uma carteira %1 offiline ou uma carteira de hardware compatível com PSBT</translation>
+ <source>Create Unsigned</source>
+ <translation>Criar sem assinatura</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Salvar informação de transação</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transação assinada parcialmente (binária) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT salva</translation>
</message>
<message>
<source>or</source>
@@ -2390,6 +2526,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Pode aumentar a taxa depois (sinaliza substituir-por-taxa, 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>
+ <translation>Por favor, reveja sua proposta de transação. Isto irá produzir uma Transação de Bitcoin parcialmente assinada (PSBT, sigla em inglês) a qual você pode salvar ou copiar e então assinar com por exemplo uma carteira %1 offiline ou uma PSBT compatível com carteira de hardware.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Por favor, reveja a sua transação.</translation>
</message>
@@ -2418,18 +2558,10 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Confirmar a proposta de transação</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copiar PSBT para área de transferência</translation>
- </message>
- <message>
<source>Send</source>
<translation>Enviar</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copiado</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Saldo apenas para visualização:</translation>
</message>
@@ -3211,12 +3343,28 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Fechar a carteira durante demasiado tempo pode resultar em ter de resincronizar a cadeia inteira se pruning estiver ativado.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Fechar todas carteiras.</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Você tem certeza que deseja fechar todas as carteira?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nenhuma carteira foi carregada</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Nenhuma carteira foi carregada
+Ir para o arquivo &gt; Abrir carteira para carregar a carteira
+- OU -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Criar novo carteira</translation>
</message>
</context>
<context>
@@ -3289,6 +3437,30 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Exportar os dados no separador atual para um ficheiro</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Erro</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Incapaz de decifrar a PSBT da área de transferência (base64 inválida)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Carregar dados de transação</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Transação parcialmente assinada (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>Arquivo PSBT deve ser menor que 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Incapaz de decifrar a PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Cópia de Segurança da Carteira</translation>
</message>
@@ -3332,10 +3504,6 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Poda: a última sincronização da carteira vai além dos dados podados. Precisa de -reindex (descarregar novamente a cadeia de blocos completa em caso de nó podado)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Erro: surgiu um erro fatal interno. Veja o ficheiro debug.log para mais informação</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>A reduzir a blockstore...</translation>
</message>
@@ -3348,10 +3516,6 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Os programadores de %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Não é possível gerar uma chave de alterar endereço. Não há chaves na keypool interna e não podem ser geradas nenhumas chaves.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Não foi possível obter o bloqueio de escrita no da pasta de dados %s. %s provavelmente já está a ser executado.</translation>
</message>
@@ -3400,14 +3564,6 @@ Nota: como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por u
<translation>Aviso: parece que nós não estamos de acordo com os nossos pontos! Poderá ter que atualizar, ou outros pontos podem ter que ser atualizados.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d dos últimos 100 blocos têm uma versão inesperada</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrompido, a recuperação falhou</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>- máximo do banco de memória deverá ser pelo menos %d MB</translation>
</message>
@@ -3533,10 +3689,6 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>A carregar endereços de P2P...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Erro: O espaço disponível no disco é demasiado pequeno!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>A carregar a lista de banir...</translation>
</message>
@@ -3601,6 +3753,14 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Erro: a escuta de ligações de entrada falhou (escuta devolveu o erro %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s corrompido. Tente usar a ferramenta de carteira bitcoin-wallet para salvar ou restaurar um backup.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Não é possível atualizar uma carteira divida do tipo não-HD sem atualizar para ser compatível com divisão prévia da keypool. Por favor use a versão 169900 ou sem especificar nenhuma versão.</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>Montante inválido para -maxtxfee=&lt;amount&gt;: '%s' (deverá ser, no mínimo, a taxa mínima de propagação de %s, de modo a evitar transações bloqueadas)</translation>
</message>
@@ -3609,10 +3769,34 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>O montante da transação é demasiado baixo após a dedução da taxa</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>Este erro pode ocorrer se a carteira não foi desligada corretamente e foi carregada da ultima vez usando uma compilação com uma versão mais recente da Berkeley DB. Se sim, por favor use o programa que carregou esta carteira da ultima vez.</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>Este é a taxa de transação máxima que você paga (em adição à taxa normal) para priorizar evitar gastos parciais sobre seleção de moeda normal.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Transação precisa uma mudança de endereço, mas nós não podemos gerar isto. Por favor chame keypoolrefill primeiro.</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>Necessita reconstruir a base de dados, utilizando -reindex para voltar ao modo sem poda. Isto irá descarregar novamente a cadeia de blocos completa</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Um erro fatal interno occoreu, veja o debug.log para detalhes</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Não é possível ajustar -peerblockfilters sem -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Espaço de disco é muito pouco!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Erro ao ler da base de dados. A encerrar.</translation>
</message>
@@ -3625,6 +3809,14 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Erro: espaço em disco demasiado baixo para %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>A keypool esgotou-se, por favor execute primeiro keypoolrefill1</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>A variação da taxa (%s) é menor que a mínima variação de taxa (%s) configurada.</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Endereço -onion ou hostname inválido: '%s'</translation>
</message>
@@ -3645,6 +3837,10 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>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>Sem servidor de proxy especificado. Use -proxy=&lt;ip&gt; ou -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>O modo de remoção é incompatível com -blockfilterindex.</translation>
</message>
@@ -3719,10 +3915,6 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Aviso: ativadas novas regras desconhecidas (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>A limpar todas as transações da carteira...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee está definido com um valor muito alto! Taxas desta magnitude podem ser pagas numa única transação.</translation>
</message>
@@ -3735,10 +3927,6 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Comprimento total da entrada da versão de rede (%i) excede o comprimento máximo (%i). Reduzir o número ou o tamanho de uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Atenção: o ficheiro da carteira está corrompido, foram recuperados dados! Original %s guardado como %s em %s; se o seu saldo ou as transações estiverem incorretos, deve fazer o restauro de uma cópia de segurança.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s está demasiado elevado!</translation>
</message>
@@ -3783,10 +3971,6 @@ A pasta de blocos especificados "%s" não existe.</translation>
<translation>Fundos insuficientes</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Não é possível atualizar uma carteira dividida não-HD sem atualizar para ser compatível com a keypool antes da divisão. Use -upgradewallet=169900 ou -upgradewallet sem especificar nenhuma versão.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Falha na estimativa de taxa. A taxa alternativa de recurso está desativada. Espere alguns blocos ou ative -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_pt_BR.ts b/src/qt/locale/bitcoin_pt_BR.ts
index efd437fb1d..71b4bd2640 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>Clique com o botão direito para editar o endereço ou rótulo</translation>
+ <translation>Right-click to edit address or label</translation>
</message>
<message>
<source>Create a new address</source>
@@ -70,8 +70,10 @@
<translation>Estes são os seus endereços para enviar pagamentos. Sempre cheque a quantia e o endereço do destinatário antes de enviar moedas.</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.</source>
- <translation>Esses são seus endereços de Bitcoin para receber pagamentos. Utilize o botão Criar novo endereço de recebimento na aba receber para criar um novo endereço</translation>
+ <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>Estes são seus endereços Bitcoin para receber pagamentos. Use o botão 'Criar novos endereços de recebimento' na barra receber para criar novos endereços.
+Somente é possível assinar com endereços do tipo 'legado'.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>Atualizado</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Carregar 'PSBT' do arquivo...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Carregar Transação de Bitcoin Parcialmente Assinada</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Carregar PSBT da área de transferência...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Carregar Transação de Bitcoin Parcialmente Assinada da área de transferência</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Janela do Nó</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Fechar carteira</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Fechar Todas as Carteiras...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Fechar todas as carteiras</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Mostrar a mensagem de ajuda do %1 para obter uma lista com possíveis opções de linha de comando Bitcoin</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Mascarar valores</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Mascarar os valores na barra Resumo</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>carteira padrão</translation>
</message>
@@ -630,8 +664,12 @@
<translation>Carteira está &lt;b&gt;criptografada&lt;/b&gt; e atualmente &lt;b&gt;bloqueada&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Um erro fatal ocorreu. Bitcoin não pode continuar em segurança e irá fechar.</translation>
+ <source>Original message:</source>
+ <translation>Mensagem original:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Aconteceu um erro fatal. %1 não pode continuar com segurança e será fechado.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Criar Carteira Vazia</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Utilize os descritores para gerenciamento do scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Carteira descritora.</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Criar</translation>
</message>
@@ -1139,10 +1185,6 @@
<translation>Mostra se o proxy padrão fornecido SOCKS5 é utilizado para encontrar participantes por este tipo de rede.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Use um proxy SOCKS&amp;5 separado para alcançar participantes via serviços ocultos Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Esconder ícone da bandeja do sistema.</translation>
</message>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conecte-se à rede Bitcoin através de um proxy SOCKS5 separado para utilizar serviços ocultos Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Janela</translation>
</message>
@@ -1319,6 +1357,14 @@
<translation>Mostrar ou não opções de controle da moeda.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Conectar à rede Bitcoin através de um proxy SOCKS5 separado para serviços Tor onion.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Use um proxy SOCKS&amp;5 separado para alcançar pares via serviços Tor onion:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;URLs de transação de terceiros</translation>
</message>
@@ -1453,6 +1499,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Balanço total em endereços monitorados</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Modo de privacidade ativado para a barra Resumo. Para revelar os valores, desabilite Configurações-&gt;Mascarar valores</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Diálogo</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Assinar Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Transmitir Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Copiar para Área de Transferência</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Salvar...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Fechar</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Falhou ao carregar transação: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Falhou ao assinar transação: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Não foi possível assinar mais nenhuma entrada.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Assinou %1 entradas, mas ainda são necessárias mais assinaturas.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Transação assinada com sucesso. Transação está pronta para ser transmitida.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Erro desconhecido ao processar transação.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Transação transmitida com sucesso! ID da Transação: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Transmissão de transação falhou: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT copiada para área de transferência.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Salvar Dados de Transação</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transação Parcialmente Assinada (Binário) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT salvo no disco.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>* Envia %1 para %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Não foi possível calcular a taxa de transação ou quantidade total da transação.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Paga taxa de transação:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Valor total</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ou</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Transação possui %1 entradas não assinadas.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Transação está faltando alguma informação sobre entradas.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Transação ainda precisa de assinatura(s).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Mas esta carteira não pode assinar transações.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Mas esta carteira não possui as chaves certas.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Transação está assinada totalmente e pronta para transmitir.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Situação da transação é desconhecida</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1619,6 +1792,10 @@
<translation>Erro: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Erro ao iniciar configurações: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 ainda não terminou com segurança...</translation>
</message>
@@ -1717,10 +1894,6 @@
<translation>Corrente de blocos</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Quantidade atual de blocos</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Pool de Memória</translation>
</message>
@@ -1765,10 +1938,6 @@
<translation>Selecione um nó para ver informações detalhadas.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Lista branca</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direção</translation>
</message>
@@ -1805,6 +1974,10 @@
<translation>Janela do Nó</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Altura de bloco atual</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>Abrir o arquivo de log de depuração do %1 localizado no diretório atual de dados. Isso pode levar alguns segundos para arquivos de log grandes.</translation>
</message>
@@ -1817,12 +1990,12 @@
<translation>Aumentar o tamanho da fonte</translation>
</message>
<message>
- <source>Services</source>
- <translation>Serviços</translation>
+ <source>Permissions</source>
+ <translation>Permissões</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Pontuação de Banimento</translation>
+ <source>Services</source>
+ <translation>Serviços</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2146,6 @@
<translation>Saída</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Sim</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Não</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Desconhecido</translation>
</message>
@@ -2079,56 +2244,60 @@
<source>Copy amount</source>
<translation>Copiar quantia</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Não foi possível desbloquear a carteira.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Não foi possível gerar novo endereço %1 </translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Código QR</translation>
+ <source>Request payment to ...</source>
+ <translation>Solicitar pagamento para...</translation>
</message>
<message>
- <source>Copy &amp;URI</source>
- <translation>Copiar &amp;URI</translation>
- </message>
- <message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Copiar Endereço</translation>
+ <source>Address:</source>
+ <translation>Endereço:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Salvar Imagem...</translation>
+ <source>Amount:</source>
+ <translation>Quantia:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Pedido de pagamento para %1</translation>
+ <source>Label:</source>
+ <translation>Etiqueta:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Informação do pagamento</translation>
+ <source>Message:</source>
+ <translation>Mensagem:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Carteira:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Endereço</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Copiar &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Quantia</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Copiar Endereço</translation>
</message>
<message>
- <source>Label</source>
- <translation>Rótulo</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Salvar Imagem...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Mensagem</translation>
+ <source>Request payment to %1</source>
+ <translation>Pedido de pagamento para %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Carteira</translation>
+ <source>Payment information</source>
+ <translation>Informação do pagamento</translation>
</message>
</context>
<context>
@@ -2377,8 +2546,20 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Tem certeza que deseja enviar?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>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>
+ <source>Create Unsigned</source>
+ <translation>Criar Não Assinado</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Salvar Dados de Transação</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Transação Parcialmente Assinada (Binário) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT salvo</translation>
</message>
<message>
<source>or</source>
@@ -2389,6 +2570,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Você pode aumentar a taxa depois (sinaliza 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>
+ <translation>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>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Revise a sua transação.</translation>
</message>
@@ -2417,18 +2602,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Confirmar a proposta de transação</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Copiar PSBT para a área de transferência</translation>
- </message>
- <message>
<source>Send</source>
<translation>Enviar</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT copiado</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Saldo monitorado:</translation>
</message>
@@ -3210,12 +3387,26 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Manter a carteira fechada por muito tempo pode resultar na necessidade de ressincronizar a block chain se prune está ativado.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Fechar todas as carteiras</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Tem certeza que quer fechar todas as carteiras?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nenhuma carteira carregada.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Nenhuma carteira foi carregada. Vá para o menu Arquivo &gt; Abrir Carteira para carregar sua Carteira. -OU-</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Criar uma nova carteira</translation>
</message>
</context>
<context>
@@ -3288,6 +3479,30 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Exportar os dados da guia atual para um arquivo</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Erro</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Não foi possível decodificar PSBT da área de transferência (base64 inválido)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Carregar Dados de Transação</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Transação Parcialmente Assinada (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>Arquivo PSBT deve ser menor que 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Não foi possível decodificar PSDBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup da carteira</translation>
</message>
@@ -3331,10 +3546,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>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>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Erro: Um erro interno fatal ocorreu, veja debug.log para detalhes</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Prunando os blocos existentes...</translation>
</message>
@@ -3347,10 +3558,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Desenvolvedores do %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Não é possível criar uma chave de endereço de troco. Nenhuma chave disponível na keypool interna e não é possível gerar novas chaves.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Não foi possível obter exclusividade de escrita no endereço %s. O %s provavelmente já está sendo executado.</translation>
</message>
@@ -3363,6 +3570,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>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>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation>Mais de um endereço onion associado é fornecido. Usando %s para automaticamento criar serviço onion Tor.</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>Por favor verifique se a data e o horário de seu computador estão corretos. Se o relógio de seu computador estiver incorreto, %s não funcionará corretamente.</translation>
</message>
@@ -3371,6 +3582,18 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Por favor contribua se você entender que %s é útil. Visite %s para mais informações sobre o software.</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: Falha ao preparar a confirmação para buscar a versão do programa da carteira sqlite: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Falhou em preparar confirmação para buscar a id da aplicação: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation>SQLiteDatabase: Desconhecida a versão %d do programa da carteira sqlite. Apenas a versão %d é suportada</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>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>
@@ -3399,14 +3622,6 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Atenção: Nós não parecemos concordar plenamente com nossos pares! Você pode precisar atualizar ou outros pares podem precisar atualizar.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d dos últimos 100 blocos possuem versão inesperada.</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrompido, recuperação falhou</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool deve ser pelo menos %d MB</translation>
</message>
@@ -3483,6 +3698,10 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Falha ao escanear novamente a carteira durante a inicialização</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Falha ao verificar a base de dados</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Importando...</translation>
</message>
@@ -3511,6 +3730,30 @@ Nota: Como a taxa é calculada por byte, uma taxa de "100 satoshis por kB" por
<translation>Quantidade inválida para -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Falhou em executar a confirmação para verificar a base de dados: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: Falha ao burscar a versão do programa da carteira sqlite: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Falha ao procurar a id da aplicação: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Falhou em preparar confirmação para verificar a base de dados: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase: Falha ao ler o erro de verificação da base de dados: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase: Id da aplicação inesperada. Esperada %u, got %u</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>
Diretório de blocos especificados "%s" não existe.</translation>
@@ -3532,10 +3775,6 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Carregando endereços P2P...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Erro: Espaço em disco está baixo!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Carregando lista de banidos...</translation>
</message>
@@ -3600,6 +3839,14 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Erro: Escutar conexões de entrada falhou (vincular retornou erro %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s está corrompido. Tente usar a ferramenta de carteira bitcoin-wallet para salvamento ou restauração de backup.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Não é possível fazer upgrade de uma carteira dividida não HD sem fazer upgrade para ser compatível com a keypool antes da divisão. Use -upgradewallet=169900 ou -upgradewallet sem especificar nenhuma versão.</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>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>
@@ -3608,10 +3855,34 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>A quantia da transação é muito pequena para mandar depois de deduzida a taxa</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>Este erro pode ocorrer se a sua carteira não foi desligada de forma correta e foi recentementa carregada utilizando uma nova versão do Berkeley DB. Se isto ocorreu então por favor utilize a mesma versão na qual esta carteira foi utilizada pela última vez.</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>Esta é a taxa máxima de transação que você pode pagar (além da taxa normal) para priorizar a evasão parcial de gastos em vez da seleção regular de moedas.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Transações precisam de um endereço de troco, mas nós não podemos gerá-lo. Por favor, faça um keypoolrefill primeiro.</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>Você precisa reconstruir o banco de dados usando -reindex para sair do modo prune. Isso irá causar o download de todo o blockchain novamente.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Aconteceu um erro interno fatal, veja os detalhes em debug.log</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Não pode definir -peerblockfilters sem -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Espaço em disco muito baixo!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Erro ao ler o banco de dados. Encerrando.</translation>
</message>
@@ -3624,6 +3895,14 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Erro: Espaço em disco menor que %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Keypool exaurida, por gentileza execute keypoolrefill primeiro</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Taxa de taxa (%s) é menor que a configuração da taxa de taxa (%s)</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Endereço -onion ou nome do servidor inválido: '%s'</translation>
</message>
@@ -3644,6 +3923,10 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>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>Nenhum servidor proxy especificado. Use -proxy=&lt;ip&gt; ou proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Modo prune é incompatível com o parâmetro -blockfilterindex.</translation>
</message>
@@ -3718,10 +4001,6 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Aviso: Novas regras desconhecidas foram ativadas (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Aniquilando todas as transações da carteira...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>A valor especificado de -maxtxfee está muito alto! Taxas grandes assim podem ser atribuidas numa transação única.</translation>
</message>
@@ -3734,10 +4013,6 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>O tamanho total da string de versão da rede (%i) excede o tamanho máximo (%i). Reduza o número ou tamanho de uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Atenção: Arquivo da carteira corrompido, dados recuperados! Original %s salvo como %s em %s; se seu saldo ou transações estiverem incorretos, você deve restaurar o backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s está muito alto!</translation>
</message>
@@ -3782,10 +4057,6 @@ Diretório de blocos especificados "%s" não existe.</translation>
<translation>Saldo insuficiente</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Não é possível fazer upgrade de uma carteira dividida não HD sem fazer upgrade para ser compatível com a keypool antes da divisão. Use -upgradewallet=169900 ou -upgradewallet sem especificar nenhuma versão.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Falha na estimativa de taxa. Fallbackfee desativada. Espere alguns blocos ou ative -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ro.ts b/src/qt/locale/bitcoin_ro.ts
index 310aa000e0..6adb5cacc1 100644
--- a/src/qt/locale/bitcoin_ro.ts
+++ b/src/qt/locale/bitcoin_ro.ts
@@ -609,11 +609,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Portofelul este &lt;b&gt;criptat&lt;/b&gt; iar în momentul de faţă este &lt;b&gt;blocat&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>A survenit o eroare fatală. Bitcoin nu mai poate continua în siguranţă şi se va opri.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1067,10 +1063,6 @@
<translation>Arata daca proxy-ul SOCKS5 furnizat implicit este folosit pentru a gasi parteneri via acest tip de retea.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Foloseste un proxy SOCKS&amp;5 separat pentru a gasi parteneri via servicii TOR ascunse</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Ascunde icon-ul din system tray.</translation>
</message>
@@ -1199,10 +1191,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Conectare la reteaua Bitcoin printr-un proxy SOCKS5 separat pentru serviciile TOR ascunse.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Fereastră</translation>
</message>
@@ -1373,7 +1361,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>Soldul dvs. total în adresele doar-supraveghere</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Suma totală</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>sau</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1609,10 +1608,6 @@
<translation>Lanţ de blocuri</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Numărul curent de blocuri</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Pool Memorie</translation>
</message>
@@ -1657,10 +1652,6 @@
<translation>Selectaţi un partener pentru a vedea informaţiile detaliate.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direcţie</translation>
</message>
@@ -1705,10 +1696,6 @@
<translation>Servicii</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Scor Ban</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Timp conexiune</translation>
</message>
@@ -1857,14 +1844,6 @@
<translation>Ieşire</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nu</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Necunoscut</translation>
</message>
@@ -1951,12 +1930,24 @@
<source>Copy amount</source>
<translation>Copiază suma</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Portofelul nu a putut fi deblocat.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Cod QR</translation>
+ <source>Amount:</source>
+ <translation>Sumă:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Mesaj:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Portofel:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1978,30 +1969,6 @@
<source>Payment information</source>
<translation>Informaţiile plată</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresă</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Cantitate</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etichetă</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Mesaj</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portofel</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -3006,8 +2973,8 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nu a fost încărcat nici un portofel.</translation>
+ <source>Create a new wallet</source>
+ <translation>Crează un portofel nou</translation>
</message>
</context>
<context>
@@ -3068,6 +3035,10 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Exportă datele din tab-ul curent într-un fişier</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Eroare</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup portofelul electronic</translation>
</message>
@@ -3111,10 +3082,6 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Reductie: ultima sincronizare merge dincolo de datele reductiei. Trebuie sa faceti -reindex (sa descarcati din nou intregul blockchain in cazul unui nod redus)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Eroare: S-a produs o eroare interna fatala, vedeti debug.log pentru detalii</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Reductie blockstore...</translation>
</message>
@@ -3175,14 +3142,6 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Atenţie: Aparent, nu sîntem de acord cu toţi partenerii noştri! Va trebui să faceţi o actualizare, sau alte noduri necesită actualizare.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d din ultimele 100 blocuri a o versiune neasteptata</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corupt, salvare nereuşită</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool trebuie sa fie macar %d MB</translation>
</message>
@@ -3439,10 +3398,6 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Atentie: se activeaza reguli noi necunoscute (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Şterge toate tranzacţiile din portofel...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee este setata foarte sus! Se pot plati taxe de aceasta marime pe o singura tranzactie.</translation>
</message>
@@ -3455,10 +3410,6 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Lungimea totala a sirului versiunii retelei (%i) depaseste lungimea maxima (%i). Reduceti numarul sa dimensiunea uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Atenţie: fişierul portofelului este corupt, date salvate! Fişierul %s a fost salvat ca %s in %s; dacă balanta sau tranzactiile sunt incorecte ar trebui să restauraţi dintr-o copie de siguranţă.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s este setata foarte sus!</translation>
</message>
@@ -3503,10 +3454,6 @@ Nota: Cum taxa este calculata per byte, o taxa de "100 satoshi per kB" pentru o
<translation>Fonduri insuficiente</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Nu se poate actualiza un portofel split HD fără a fi actualizat pentru a sprijini keypool-ul pre divizat. Vă rugăm să folosiți -upgradewallet=169900 sau -upgradewallet fără nicio versiune specificată.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Estimarea taxei a esuat. Taxa implicita este dezactivata. Asteptati cateva blocuri, sau activati -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts
index 4b063eb201..ba327643d6 100644
--- a/src/qt/locale/bitcoin_ru.ts
+++ b/src/qt/locale/bitcoin_ru.ts
@@ -70,8 +70,10 @@
<translation>Это ваши Биткойн-адреса для отправки платежей. Всегда проверяйте количество и адрес получателя перед отправкой перевода.</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.</source>
- <translation>Это ваши Биткойн-адреса для приёма платежей. Используйте кнопку «Создать новый адрес для получения» на вкладке Получить, чтобы создать новые адреса.</translation>
+ <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>Это ваши Биткойн адреса для получения платежей. Используйте кнопку «Создать новый адрес для получения» на вкладке Получить, чтобы создать новые адреса.
+Подписание возможно только с адресами типа "legacy".</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>Готов</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Загрузить PSBT из файла...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Загрузить Частично Подписанные Биткойн Транзакции (PSBT)</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Загрузить PSBT из буфера обмена...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Загрузить Частично Подписанную Транзакцию из буфера обмена</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Окно узла</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Закрыть кошелёк</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Закрыть все кошельки</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Закрыть все кошельки</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Показать помощь по %1, чтобы получить список доступных параметров командной строки</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Скрыть значения</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Скрыть значения на вкладке Обзор</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>Кошелёк по умолчанию</translation>
</message>
@@ -630,8 +664,13 @@
<translation>Кошелёк &lt;b&gt;зашифрован&lt;/b&gt; и сейчас &lt;b&gt;заблокирован&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Произошла критическая ошибка. Биткойн больше не может продолжать безопасную работу и будет закрыт.</translation>
+ <source>Original message:</source>
+ <translation>Исходное сообщение:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Произошла критическая ошибка. %1 больше не может продолжать безопасную работу и будет закрыт.
+ </translation>
</message>
</context>
<context>
@@ -835,6 +874,14 @@
<translation>Создать пустой кошелёк</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Использовать дескриптор для управления scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Дескриптор кошелька</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Создать</translation>
</message>
@@ -1139,10 +1186,6 @@
<translation>Показывает, используется ли прокси SOCKS5 по умолчанию для доступа к узлам через этот тип сети.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Использовать отдельные прокси SOCKS&amp;5 для подключения к узлам через скрытые сервисы Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Убрать значок с области уведомлений.</translation>
</message>
@@ -1275,10 +1318,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Подключаться к Биткойн-сети через отдельный прокси SOCKS5 для скрытых сервисов Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Окно</translation>
</message>
@@ -1319,6 +1358,14 @@
<translation>Показывать ли опцию управления монетами.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Подключаться к Биткойн-сети через отдельный прокси SOCKS5 для скрытых сервисов Tor.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Использовать отдельный прокси SOCKS&amp;5 для соединения с узлами через скрытые сервисы Tor:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;Ссылки на транзакции сторонних сервисов</translation>
</message>
@@ -1453,6 +1500,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Текущий общий баланс на адресах наблюдения</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Режим приватности включен для вкладки обзора. Чтобы показать данные, отключите настройку Скрыть Значения.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Подписать транзакцию</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Отправить Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Скопировать в буфер обмена</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Сохранить...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Закрыть</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Не удалось загрузить транзакцию: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Не удалось подписать транзакцию: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Не удалось подписать оставшиеся входы.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Подписано %1 входов, но требуется больше подписей.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Транзакция успешно подписана. Транзакция готова к отправке.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Неизвестная ошибка во время обработки транзакции.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Транзакция успешно отправлена! ID транзакции: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Отправка транзакции не удалась: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT скопирован в буфер обмена</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Сохранить данные о транзакции</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Частично Подписанная Транзакция (Бинарный файл) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT сохранён на диск.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>* Отправляет %1 к %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Не удалось сосчитать сумму комиссии или общую сумму транзакции.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Платит комиссию:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Общая сумма</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>или</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Транзакция имеет %1 неподписанных входов.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Транзакция имеет недостаточно информации о некоторых входах.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Транзакция требует по крайней мере одну подпись.</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Но этот кошелёк не может подписывать транзакции.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Но этот кошелёк не имеет необходимые ключи.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Транзакция полностью подписана, и готова к отправке.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Статус транзакции неизвестен.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1619,6 +1793,10 @@
<translation>Ошибка: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Ошибка инициализации настроек: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 ещё не завершился безопасно...</translation>
</message>
@@ -1717,10 +1895,6 @@
<translation>Блокчейн</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Текущее количество блоков</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Пул памяти</translation>
</message>
@@ -1765,10 +1939,6 @@
<translation>Выберите пира для просмотра детальной информации.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Белый список</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Направление</translation>
</message>
@@ -1805,6 +1975,10 @@
<translation>Окно узла</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Текущая высота блока</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>Открыть отладочный лог-файл %1 с текущего каталога данных. Для больших лог-файлов это может занять несколько секунд.</translation>
</message>
@@ -1817,12 +1991,12 @@
<translation>Увеличить размер шрифта</translation>
</message>
<message>
- <source>Services</source>
- <translation>Сервисы</translation>
+ <source>Permissions</source>
+ <translation>Права</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Запретить счёт</translation>
+ <source>Services</source>
+ <translation>Сервисы</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2147,6 @@
<translation>Исходящий</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Нет</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Неизвестно</translation>
</message>
@@ -2079,56 +2245,60 @@
<source>Copy amount</source>
<translation>Копировать сумму</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Невозможно разблокировать кошелёк.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Не удалось сгенерировать новый %1 адрес</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-код</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Копировать &amp;URI</translation>
+ <source>Request payment to ...</source>
+ <translation>Запросить платёж на ...</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Копировать &amp;Адрес</translation>
+ <source>Address:</source>
+ <translation>Адрес:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Сохранить изображение...</translation>
+ <source>Amount:</source>
+ <translation>Количество:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Запросить платёж на %1</translation>
+ <source>Label:</source>
+ <translation>Метка:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Информация о платеже</translation>
+ <source>Message:</source>
+ <translation>Сообщение:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Кошелёк:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Адрес</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Копировать &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Количество</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Копировать &amp;Адрес</translation>
</message>
<message>
- <source>Label</source>
- <translation>Метка</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Сохранить изображение...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Сообщение</translation>
+ <source>Request payment to %1</source>
+ <translation>Запросить платёж на %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Кошелёк</translation>
+ <source>Payment information</source>
+ <translation>Информация о платеже</translation>
</message>
</context>
<context>
@@ -2354,7 +2524,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>Creates a Partially Signed Bitcoin Transaction (PSBT) for use with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
+ <translation>Создает Частично Подписанную Биткойн Транзакцию (PSBT), чтобы использовать её, например, с оффлайн %1 кошельком, или PSBT-совместимым аппаратным кошельком.</translation>
</message>
<message>
<source> from wallet '%1'</source>
@@ -2377,8 +2547,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Вы действительно хотите выполнить отправку?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
+ <source>Create Unsigned</source>
+ <translation>Создать Без Подписи</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Сохранить данные о транзакции</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Частично Подписанная Транзакция (Бинарный файл) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT сохранён</translation>
</message>
<message>
<source>or</source>
@@ -2389,6 +2571,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Вы можете увеличить комиссию позже (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>
+ <translation>Пожалуйста, пересмотрите ваше транзакционное предложение. Это создаст Частично Подписанную Биткойн Транзакцию (PSBT), которую можно сохранить или копировать и использовать для подписи, например, с оффлайн %1 кошельком, или PSBT-совместимым аппаратным кошельком.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Пожалуйста, ознакомьтесь с вашей транзакцией.</translation>
</message>
@@ -2417,18 +2603,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Подтвердите предложенную транзакцию</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Копировать PSBT в буфер обмена</translation>
- </message>
- <message>
<source>Send</source>
<translation>Отправить</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT скопирована</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Баланс только для просмотра:</translation>
</message>
@@ -3210,12 +3388,28 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Слишком длительное закрытие кошелька может привести к необходимости повторной синхронизации всей цепочки, если включено сокращение.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Закрыть все кошельки</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Вы уверенны, что хотите закрыть все кошельки?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Не был загружен ни один кошелёк.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Кошелёк не был загружен.
+Откройте вкладку Файл &gt; Открыть Кошелёк чтобы загрузить кошелёк.
+- ИЛИ -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Создать новый кошелёк</translation>
</message>
</context>
<context>
@@ -3288,6 +3482,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Экспортировать данные текущей вкладки в файл</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Ошибка</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Не удалось декодировать PSBT из буфера обмена (неверный base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Загрузить данные о транзакции</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Частично Подписанная Транзакция (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>Файл PSBT должен быть меньше 100 мегабит.</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Не удалось декодировать PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Создать резервную копию кошелька</translation>
</message>
@@ -3331,10 +3549,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Удаление: последняя синхронизация кошелька вышла за рамки удаленных данных. Вам нужен -reindex (скачать всю цепь блоков в случае удаленного узла)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Ошибка: произошла критическая внутренняя ошибка, для получения деталей см. debug.log</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Очистка хранилища блоков...</translation>
</message>
@@ -3347,10 +3561,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Разработчики %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Невозможно сгенерировать ключ изменения адреса. Нет ключей во внутреннем пуле ключей и не может генерировать ключи.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Невозможно заблокировать каталог данных %s. %s, возможно, уже работает.</translation>
</message>
@@ -3363,6 +3573,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Ошибка чтения %s! Все ключи прочитаны верно, но данные транзакций или записи адресной книги могут отсутствовать или быть неправильными.</translation>
</message>
<message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation>Предоставлен более чем один адрес подключения к скрытым сервисам. %s используется для подключения к автоматически созданному сервису Tor.</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>Пожалуйста, убедитесь в корректности установки времени и даты на вашем компьютере! Если время установлено неверно, %s не будет работать правильно.</translation>
</message>
@@ -3371,6 +3585,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Пожалуйста, внесите свой вклад, если вы найдете %s полезными. Посетите %s для получения дополнительной информации о программном обеспечении.</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: Не удалось приготовить утверждение чтобы загрузить sqlite кошелёк версии: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Не удалось приготовить утверждение чтобы загрузить id приложения: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation>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>База данных блоков содержит блок, который появляется из будущего. Это может произойти из-за некорректно установленных даты и времени на вашем компьютере. Остается только перестраивать базу блоков, если вы уверены, что дата и время корректны.</translation>
</message>
@@ -3399,14 +3625,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Внимание: Мы не полностью согласны с подключенными участниками! Вам или другим участникам, возможно, следует обновиться.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d из последних 100 блоков имеют неожиданную версию</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s поврежден, восстановить не удалось</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool должен быть как минимум %d Мб</translation>
</message>
@@ -3483,6 +3701,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Не удалось повторно сканировать кошелёк во время инициализации</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Не удалось проверить базу данных</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Выполняется импорт...</translation>
</message>
@@ -3511,6 +3733,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Недопустимая сумма для -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Не удалось произвести проверку базы данных: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: Не удалось загрузить sqlite кошелёк версии: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Не удалось загрузить id приложения: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Не удалось приготовить утверждение для проверки базы данных: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase: Ошибка при проверке базы данных: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase: Неожиданный id приложения. Ожидалось %u, а получено %u</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>Указанная директория с блоками "%s" не существует.</translation>
</message>
@@ -3531,10 +3777,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Выполняется загрузка P2P-адресов...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Ошибка: мало места на диске!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Загрузка черного списка...</translation>
</message>
@@ -3599,6 +3841,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Ошибка: Не удалось начать прослушивание входящих подключений (прослушивание вернуло ошибку %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s испорчен. Попробуйте восстановить с помощью инструмента bitcoin-wallet, или используйте резервную копию.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Невозможно обновить не разделенный HD кошелёк без обновления для поддержки предварительно разделенного пула ключей. Пожалуйста, используйте версию 169900 или повторите без указания версии.</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>Неверное значение для -maxtxfee=&lt;amount&gt;: '%s' (минимальная комиссия трансляции %s для предотвращения зависания транзакций)</translation>
</message>
@@ -3607,10 +3857,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Сумма транзакции за вычетом комиссии слишком мала</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>Данная ошибка может произойти в том случае, если этот кошелёк не был правильно закрыт и в последний раз был загружен используя версию с более новой версией Berkley DB. Если это так, воспользуйтесь той программой, в которой этот кошелёк открывался в последний раз.</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>Это максимальная транзакция, которую вы заплатите (в добавок к обычной плате) для избежания затрат по причине отбора монет.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Для транзакции требуется адрес сдачи, но сгенерировать его не удалось. Пожалуйста, сначала выполните keypoolrefill.</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>Вам необходимо пересобрать базу данных с помощью -reindex, чтобы вернуться к полному режиму. Это приведёт к перезагрузке всей цепи блоков</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Ошибка: произошла критическая внутренняя ошибка, для получения деталей см. debug.log</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Не удалось поставить -peerblockfilters без использования -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Мало места на диске!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Ошибка чтения с базы данных, выполняется закрытие.</translation>
</message>
@@ -3623,6 +3897,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Ошибка: На диске недостаточно места для %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Пул ключей опустел, пожалуйста сначала выполните keypoolrefill</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Количество комисии (%s) меньше чем настроенное минимальное количество комисии (%s).</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Неверный -onion адрес или имя хоста: '%s'</translation>
</message>
@@ -3643,6 +3925,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Необходимо указать порт с -whitebind: '%s'</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>Не указан прокси сервер. Используйте -proxy=&lt;ip&gt; или -proxy=&lt;ip:port&gt;</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Режим удаления блоков несовместим с -blockfilterindex.</translation>
</message>
@@ -3717,10 +4003,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Внимание: Неизвестные правила вступили в силу (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Стираем все транзакции из кошелька...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>Установлено очень большое значение -maxtxfee. Такие большие комиссии могут быть уплачены в отдельной транзакции.</translation>
</message>
@@ -3733,10 +4015,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Текущая длина строки версии сети (%i) превышает максимальную длину (%i). Уменьшите количество или размер uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Внимание: Файл кошелька поврежден, данные восстановлены! Оригинальный %s сохранен как %s в %s; Если баланс или транзакции некорректны, вы должны восстановить файл из резервной копии.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s задан слишком высоким!</translation>
</message>
@@ -3781,10 +4059,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Недостаточно средств</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Невозможно обновить неразделенный HD кошелёк без обновления для поддержки предварительно разделенного пула ключей. Пожалуйста, используйте -upgradewallet=169900 или -upgradeallet без указания версии.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Не удалось оценить комиссию. Резервная комиссия отключена. Подождите несколько блоков или включите -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_si.ts b/src/qt/locale/bitcoin_si.ts
index bf3f976e1e..c6fb83eda2 100644
--- a/src/qt/locale/bitcoin_si.ts
+++ b/src/qt/locale/bitcoin_si.ts
@@ -54,10 +54,6 @@
<translation>මේවා ඔබගේ ගෙවීම් යැවීම සඳහා වන බිට්කොයින් ලිපින වේ. කාසි යැවීමට පෙර සෑම විටම මුදල සහ ලැබීමේ ලිපිනය පරීක්ෂා කරන්න.</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.</source>
- <translation> මේවා ඔබගේ ගෙවීම් ලැබීම සඳහා වන බිට්කොයින් ලිපින වේ. නව ලිපින සෑදීම සඳහා ලැබීම් ටැබ් එකෙහි ඇති 'නව ලැබීමේ ලිපිනයක් සාදන්න' බොත්තම භාවිතා කරන්න.</translation>
- </message>
- <message>
<source>Comma separated file (*.csv)</source>
<translation>කොමා වලින් වෙන් කරන ලද ගොනුව (* .csv)</translation>
</message>
@@ -331,6 +327,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -355,16 +354,8 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>ලිපිනය</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>අගය</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>ලේබලය</translation>
+ <source>Amount:</source>
+ <translation>අගය:</translation>
</message>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_sk.ts b/src/qt/locale/bitcoin_sk.ts
index 0b2b26c0c7..6550da8232 100644
--- a/src/qt/locale/bitcoin_sk.ts
+++ b/src/qt/locale/bitcoin_sk.ts
@@ -70,10 +70,6 @@
<translation>Toto sú Vaše Bitcoin adresy pre posielanie platieb. Vždy skontrolujte sumu a prijímaciu adresu pred poslaním mincí.</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.</source>
- <translation>Toto sú vaše Bitcoin adresy pre prijímanie platieb. Pre vytvorenie nových adries použite tlačidlo 'Vytvoriť novú prijímajúcu adresu' na karte Prijať.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopírovať adresu</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Peňaženka je &lt;b&gt;zašifrovaná&lt;/b&gt; a momentálne &lt;b&gt;zamknutá&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Vyskytla sa kritická chyba. Bitcoin nemôže ďalej bezpečne pokračovať a ukončí sa.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1139,10 +1131,6 @@
<translation>Ukazuje, či se zadaná východzia SOCKS5 proxy používá k pripojovaniu k peerom v rámci tohoto typu siete.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Použiť samostatný SOCKS&amp;5 proxy server na dosiahnutie počítačov cez skryté služby Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Skryť ikonu zo systémovej lišty.</translation>
</message>
@@ -1275,10 +1263,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Pripojiť k Bitcoinovej sieti cez separované SOCKS5 proxy pre skrytú službu Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Okno</translation>
</message>
@@ -1453,7 +1437,26 @@
<source>Current total balance in watch-only addresses</source>
<translation>Aktuálny celkový zostatok pre adries ktoré sa iba sledujú</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialóg</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Uložiť...</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Celková suma</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>alebo</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1717,10 +1720,6 @@
<translation>Reťazec blokov</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Aktuálny počet blokov</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Pamäť Poolu</translation>
</message>
@@ -1765,10 +1764,6 @@
<translation>Vyberte počítač pre zobrazenie podrobností.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Povolené</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Smer</translation>
</message>
@@ -1822,10 +1817,6 @@
<translation>Služby</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Skóre zákazu</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Dĺžka spojenia</translation>
</message>
@@ -1974,14 +1965,6 @@
<translation>Odchádzajúce</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Áno</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nie</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>neznámy</translation>
</message>
@@ -2080,12 +2063,28 @@
<source>Copy amount</source>
<translation>Kopírovať sumu</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Nepodarilo sa odomknúť peňaženku.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR kód</translation>
+ <source>Amount:</source>
+ <translation>Suma:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Popis:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Správa:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Peňaženka:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2107,30 +2106,6 @@
<source>Payment information</source>
<translation>Informácia o platbe</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Suma</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Popis</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Správa</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Peňaženka</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2414,18 +2389,10 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Potvrdiť návrh transakcie</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Skopírovať PSBT do schránky</translation>
- </message>
- <message>
<source>Send</source>
<translation>Odoslať</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT skopírovaný</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Iba sledovaný zostatok:</translation>
</message>
@@ -3207,12 +3174,12 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Zatvorenie peňaženky na príliš dlhú dobu môže mať za následok potrebu znova synchronizovať celý reťazec blokov (blockchain) v prípade, že je aktivované redukovanie blokov.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nie je načítaná peňaženka.</translation>
+ <source>Create a new wallet</source>
+ <translation>Vytvoriť novú peňaženku</translation>
</message>
</context>
<context>
@@ -3285,6 +3252,10 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Exportovať dáta v aktuálnej karte do súboru</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Chyba</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Zálohovanie peňaženky</translation>
</message>
@@ -3328,10 +3299,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Redukovanie: posledná synchronizácia peňaženky prebehla pred časmi blokov v redukovaných dátach. Je potrebné vykonať -reindex (v prípade redukovaného režimu stiahne znovu celý reťazec blokov)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Chyba: Vyskytla sa interná chyba, pre viac informácií zobrazte debug.log</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Redukovanie blockstore...</translation>
</message>
@@ -3344,10 +3311,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Vývojári %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Nie je možné vygenerovať kľúč na zmenu adresy. Nie sú dostupné žiadne kľúče a nie je možné ich ani generovať.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Nemožné uzamknúť zložku %s. %s pravdepodobne už beží.</translation>
</message>
@@ -3396,14 +3359,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Varovanie: Zjavne sa úplne nezhodujeme s našimi peer-mi! Možno potrebujete prejsť na novšiu verziu alebo ostatné uzly potrebujú vyššiu verziu.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d z posledných 100 blokov má neočakávanú verziu</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s je poškodený, záchrana zlyhala</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool musí byť najmenej %d MB</translation>
</message>
@@ -3528,10 +3483,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Načítavam P2P adresy…</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Chyba: Príliš málo miesta na disku!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Načítavam banlist...</translation>
</message>
@@ -3714,10 +3665,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Upozornenie: aktivovaná neznáme nové pravidlá (verzový bit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zmazať všetky transakcie z peňaženky...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee je nastavené veľmi vysoko! Takto vysoký poplatok môže byť zaplatebý v jednej transakcii.</translation>
</message>
@@ -3730,10 +3677,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Celková dĺžka verzie sieťového reťazca (%i) prekračuje maximálnu dĺžku (%i). Znížte počet a veľkosť komentárov.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Varovanie: Peňaženka poškodená, dáta boli zachránené! Originálna %s ako %s v %s; ak váš zostatok alebo transakcie sú nesprávne, mali by ste obnoviť zálohu.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>Hodnota %s je nastavená veľmi vysoko!</translation>
</message>
@@ -3778,10 +3721,6 @@ Poznámka: Keďže poplatok je počítaný za bajt, poplatok o hodnote "100 sato
<translation>Nedostatok prostriedkov</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Nie je možné vylepšiť peňaženku bez HD bez aktualizácie, ktorá podporuje delenie keypoolu. Použite prosím -upgradewallet=169900 alebo -upgradewallet bez špecifikovania verzie.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Odhad poplatku sa nepodaril. Fallbackfee je zakázaný. Počkajte niekoľko blokov alebo povoľte -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sl.ts b/src/qt/locale/bitcoin_sl.ts
index fffb181e76..1c84983532 100644
--- a/src/qt/locale/bitcoin_sl.ts
+++ b/src/qt/locale/bitcoin_sl.ts
@@ -70,8 +70,10 @@
<translation>To so vaši bitcoin-naslovi za pošiljanje. Pred pošiljanjem vedno preverite količino in prejemnikov naslov.</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.</source>
- <translation>To so vaši naslovi za prejemanje bitcoinov. Če želite ustvariti nov prejemni naslov, uporabite gumb za ustvarjanje novih naslovov v zavihku "prejemanje".</translation>
+ <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>To so vaši bitcoin-naslovi, ki jih uporabljate za prejemanje plačil. Za tvorbo novega naslova uporabite gumb "Ustvari nov prejemni naslov" v zavihku Prejmi.
+Podpisovanje je možno le s podedovanimi ("legacy") naslovi.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>Ažurno</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>Na&amp;loži DPBT iz datoteke...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Naloži delno podpisano bitcoin-transakcijo</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Naloži DPBT z odložišča...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Naloži delno podpisano bitcoin-transakcijo z odložišča</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Okno vozlišča</translation>
</message>
@@ -518,10 +536,26 @@
<translation>Zapri denarnico</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Zapri vse denarnice...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Zapri vse denarnice</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Pokaži %1 sporočilo za pomoč s seznamom vseh možnosti v ukazni vrstici</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>Za&amp;maskiraj vrednosti</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Zamaskiraj vrednosti v zavihku Pregled</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>privzeta denarnica</translation>
</message>
@@ -630,8 +664,12 @@
<translation>Denarnica je &lt;b&gt;šifrirana&lt;/b&gt; in trenutno &lt;b&gt;zaklenjena&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Prišlo je do usodne napake. Bitcoin ne more več varno nadaljevati in se bo zaprl.</translation>
+ <source>Original message:</source>
+ <translation>Izvorno sporočilo:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Prišlo je do usodne napake. %1 ne more več varno nadaljevati s tekom in se bo ustavil.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Ustvari prazno denarnico</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Uporabi deskriptorje za upravljanje s scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Datoteka z deskriptorji</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Ustvari</translation>
</message>
@@ -1139,10 +1185,6 @@
<translation>Prikaže, če je priloženi privzeti proxy SOCKS5 uporabljen za doseganje soležnikov prek te vrste omrežja.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Za dostop do soležnikov preko skritih storitev Tor uporabi drug posredniški strežnik SOCKS&amp;5:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Skrij ikono na sistemskem pladnju.</translation>
</message>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Poveži se v omrežje Bitcoin preko posredniškega strežnika SOCKS5 za skrite storitve Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>O&amp;kno</translation>
</message>
@@ -1319,6 +1357,14 @@
<translation>Omogoči dodatno možnost podrobnega nadzora nad posameznimi kovanci v transakcijah.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Poveži se v omrežje Bitcoin prek ločenega posredniškega strežnika SOCKS5 za storitve onion (Tor).</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Uporabi ločen posredniški strežik SOCKS5 za povezavo s soležniki prek storitev onion (Tor):</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>URL za nakazila &amp;tretjih oseb:</translation>
</message>
@@ -1453,6 +1499,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Trenutno skupno stanje sredstev na opazovanih naslovih</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>V zavihku Pregled je vklopljen zasebni način. Za prikaz vrednosti odstranite kljukico na mestu Nastavitve &gt; Zamaskiraj vrednosti.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Pogovorno okno</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Podpiši transakcijo</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Oddaj transakcijo v omrežje</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Skopiraj v odložišče</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Shrani...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Zapri</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Nalaganje transakcije je spodletelo: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Podpisovanje transakcije je spodletelo: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Ne morem podpisati več vhodov.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>%1 vhodov podpisanih, a potrebnih je več podpisov.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Transakcija je uspešno podpisana in pripravljena na oddajo v omrežje.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Neznana napaka pri obdelavi transakcije.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Transakcija uspešno oddana v omrežje. ID transakcije: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Oddaja transakcije v omrežje je spodletela: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>DPBT kopirana v odložišče.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Shrani podatke transakcije</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Delno podpisana bitcoin-transakcija (binarno) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>DPBT shranjena na disk.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>* Pošlje %1 na %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Ne morem izračunati transakcijske provizije ali skupnega zneska transakcije.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Vsebuje transakcijsko provizijo:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Skupni znesek</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>ali</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Transakcija ima toliko nepodpisanih vhodov: %1.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>Transakciji manjkajo nekateri podatki o vhodih.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Transakcija potrebuje nadaljnje podpise.</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Ta denarnica pa ne more podpisovati transakcij.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Ta denarnica pa nima pravih ključev.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Transakcija je v celoti podpisana in pripravljena za oddajo v omrežje.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Status transakcije ni znan.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1619,6 +1792,10 @@
<translation>Napaka: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Napaka pri inicializaciji nastavitev: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 se še ni varno zaprl ...</translation>
</message>
@@ -1717,10 +1894,6 @@
<translation>Veriga blokov</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Trenutno število blokov</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Čakalna vrsta transakcij</translation>
</message>
@@ -1765,10 +1938,6 @@
<translation>Izberite soležnika, o katerem si želite ogledati podrobnejše informacije.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Na seznamu dovoljenih</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Smer povezave</translation>
</message>
@@ -1805,6 +1974,10 @@
<translation>Okno vozlišča</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Višina trenutnega 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>Odpre %1 razhroščevalni dnevnik debug.log, ki se nahaja v trenutni podatkovni mapi. Če je datoteka velika, lahko postopek traja nekaj sekund.</translation>
</message>
@@ -1817,12 +1990,12 @@
<translation>Povečaj velikost pisave</translation>
</message>
<message>
- <source>Services</source>
- <translation>Storitve</translation>
+ <source>Permissions</source>
+ <translation>Dovoljenja</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Kazenske točke</translation>
+ <source>Services</source>
+ <translation>Storitve</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2146,6 @@
<translation>Odhodna</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Da</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ne</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Neznano</translation>
</message>
@@ -2079,56 +2244,60 @@
<source>Copy amount</source>
<translation>Kopiraj znesek</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Denarnice ni bilo mogoče odkleniti.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Ne morem ustvariti novega %1 naslova</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Koda</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>Kopiraj &amp;URl</translation>
+ <source>Request payment to ...</source>
+ <translation>Zahtevaj plačilo na ...</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Kopiraj &amp;naslov</translation>
+ <source>Address:</source>
+ <translation>Naslov:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Shrani sliko ...</translation>
+ <source>Amount:</source>
+ <translation>Znesek:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Zaprosi za plačilo na naslov %1</translation>
+ <source>Label:</source>
+ <translation>Oznaka:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Informacije o plačilu</translation>
+ <source>Message:</source>
+ <translation>Sporočilo:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Denarnica:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Naslov</translation>
+ <source>Copy &amp;URI</source>
+ <translation>Kopiraj &amp;URl</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Znesek</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Kopiraj &amp;naslov</translation>
</message>
<message>
- <source>Label</source>
- <translation>Oznaka</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Shrani sliko ...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Sporočilo</translation>
+ <source>Request payment to %1</source>
+ <translation>Zaprosi za plačilo na naslov %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Denarnica</translation>
+ <source>Payment information</source>
+ <translation>Informacije o plačilu</translation>
</message>
</context>
<context>
@@ -2377,8 +2546,20 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Ali ste prepričani, da želite poslati sredstva?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Prosimo, preglejte svoj predlog transakcije. Ustvarjena bo delno podpisana bitcoin-transakcija (DPBT, angl. PSBT), ki jo lahko skopirate in potem podpišete n.pr. z nepovezano (offline) %1 denarnico ali pa s hardversko denarnico, ki podpira DPBT.</translation>
+ <source>Create Unsigned</source>
+ <translation>Ustvari nepodpisano</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Shrani podatke transakcije</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Delno podpisana bitcoin-transakcija (binarno) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>DPBT shranjena</translation>
</message>
<message>
<source>or</source>
@@ -2389,6 +2570,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Provizijo lahko zvišate kasneje (signali 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>
+ <translation>Prosimo, preglejte predlog za transakcijo. Ustvarjena bo delno podpisana bitcoin-transakcija (DPBT), ki jo lahko shranite ali skopirate in potem podpišete n.pr. z nepovezano (offline) %1 denarnico ali pa s hardversko denarnico, ki podpira DPBT.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Prosimo, preglejte svojo transakcijo.</translation>
</message>
@@ -2417,18 +2602,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Potrdi predlog transakcije</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Kopiraj DPBT v odložišče</translation>
- </message>
- <message>
<source>Send</source>
<translation>Pošlji</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>DPBT skopirana</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Opazovano stanje:</translation>
</message>
@@ -3210,12 +3387,28 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Predolgo zapiranje denarnice lahko povzroči ponovno sinhronizacijo celotne verige, če je obrezovanje omogočeno.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Zapri vse denarnice</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Ste prepričani, da želite zapreti vse denarnice?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Nobena denarnica ni bila naložena.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Odprta ni nobena denarnica.
+Za odpiranje denarnice kliknite Datoteka &gt; Odpri denarnico
+- ali pa -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Ustvari novo denarnico</translation>
</message>
</context>
<context>
@@ -3288,6 +3481,30 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Izvozi podatke v trenutnem zavihku v datoteko</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Napaka</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Ne morem dekodirati DPBT z odložišča (neveljaven format base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Naloži podatke transakcije</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Delno podpisana transakcija (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>Velikost DPBT ne sme presegati 100 MiB.</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Ne morem dekodirati DPBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Izdelava varnostne kopije denarnice</translation>
</message>
@@ -3331,10 +3548,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Obrezovanje: zadnja sinhronizacija denarnice presega obrezane podatke. Izvesti morate -reindex (v primeru obrezanega načina delovanja bo potrebno znova prenesti celotno verigo blokov).</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Napaka: Med izvajanjem je prišlo do nepopravljive napake. Podrobnosti so v datoteki debug.log</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Obrezujem ...</translation>
</message>
@@ -3347,10 +3560,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>%s razvijalci</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Ne morem ustvariti ključa za naslov za vračilo. Interna zaloga ključev je prazna, novih pa ni mogoče ustvariti.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Ne morem zakleniti podatkovne mape %s. %s je verjetno že zagnan.</translation>
</message>
@@ -3371,6 +3580,18 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Prosimo, prispevajte, če se vam zdi %s uporaben. Za dodatne informacije o programski opremi obiščite %s.</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation>Baza SQLite: priprava stavka za poizvedbo verzije sheme SQLite denarnice je spodletela: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>Baza SQLite: priprava stavka za poizvedbo identifikatorja aplikacije je spodletela: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation>Baza SQLite: Neznana verzija sheme SQLite denarnice %d. Podprta je le 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>Baza podatkov blokov vsebuje blok, za katerega se zdi, da je iz prihodnosti. To je lahko posledica napačnega nastavitve datuma in časa vašega računalnika. Znova zgradite bazo podatkov samo, če ste prepričani, da sta datum in čas računalnika pravilna.</translation>
</message>
@@ -3399,14 +3620,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Opozorilo: Trenutno se s soležniki ne strinjamo v popolnosti! Mogoče bi morali vi ali drugi udeleženci posodobiti odjemalce.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d od zadnjih 100 blokov imajo nepričakovano verzijo</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s poškodovana, obnova neuspešna</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool mora biti vsaj %d MB</translation>
</message>
@@ -3483,6 +3696,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Med inicializacijo denarnice ni bilo mogoče preveriti zgodovine (rescan failed).</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Preverba podatkovne baze je spodletela.</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Uvažam ...</translation>
</message>
@@ -3511,6 +3728,30 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Neveljavna količina za -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>Baza SQLite: Izvršitev stavka za preverbo baze je spodletela: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>Baza SQLite: pridobitev verzije sheme SQLite denarnice je spodletela: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation>Baza SQLite: pridobitev identifikatorja aplikacije je spodletela: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>Baza SQLite: priprava stavka za preverbo baze je spodletela: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>Baza SQLite: branje napake pri preverjanje baze je spodletelo: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>Baza SQLite: nepričakovan identifikator aplikacije. Pričakovana vrednost je %u, dobljena vrednost je %u.</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>Vnešena podatkovna mapa za bloke "%s" ne obstaja.</translation>
</message>
@@ -3531,10 +3772,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Nalagam P2P naslove ...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Napaka: premalo prostora na disku!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Nalaganje liste blokiranih ...</translation>
</message>
@@ -3599,6 +3836,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Napaka: Ni mogoče sprejemati dohodnih povezav (vrnjena napaka: %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s je okvarjena. Lahko jo poskusite popraviti z orodjem bitcoin-wallet ali pa jo obnovite iz varnostne kopije.</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>Neveljaven znesek za -maxtxfee=&lt;amount&gt;: '%s' (mora biti najmanj provizija za %s, da se prepreči zataknjene transakcije)</translation>
</message>
@@ -3607,10 +3848,30 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Znesek transakcije je premajhen za pošiljanje po odbitku provizije</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>Ta napaka se lahko pojavi, če denarnica ni bila pravilno zaprta in je bila nazadnje naložena s programsko opremo z novejšo verzijo Berkely DB. Če je temu tako, prosimo uporabite programsko opremo, s katero je bila ta denarnica nazadnje naložena.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Transakcija potrebuje naslov za vračilo, ki pa ga ni moč ustvariti. Prosimo, najprej pokličite keypoolrefill.</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>Za vrnitev v neobrezan način morate obnoviti bazo z uporabo -reindex. To zahteva ponoven prenos celotne verige blokov.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Prišlo je do usodne notranje napake. Za podrobnosti glejte datoteko debug.log.</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Nastavitev -peerblockfilters ni veljavna brez nastavitve -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Prostora na disku je premalo!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Napaka pri branju podarkovne baze, zapiram.</translation>
</message>
@@ -3623,6 +3884,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Opozorilo: premalo prostora na disku za %s</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Napaka: bazen ključev je prazen, najprej pokličite keypoolrefill</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Neveljaven -onion naslov ali ime gostitelja: '%s'</translation>
</message>
@@ -3643,6 +3908,10 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Pri opciji -whitebind morate navesti vrata: %s</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>Posredniški strežnik (proxy) ni nastavljen. Uporabite -proxy=&lt;ip&gt; ali -proxy=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Obrezovanje ni kompatibilno z -blockfilterindex.</translation>
</message>
@@ -3717,10 +3986,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Opozorilo: neznana nova pravila aktivirana (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Brišem vse transakcije iz denarnice ...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee je nastavljen zelo visoko!</translation>
</message>
@@ -3733,10 +3998,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Skupna dolžina niza različice omrežja (%i) presega največjo dolžino (%i). Zmanjšajte število ali velikost ur.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Opozorilo: Datoteka denarnice je poškodovana, podatki so shranjeni! Izvirnik %s je bil shranjen kot %s v %s; če je prikazano stanje ali transakcije napačno, ga morate obnoviti iz varnostne kopije.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s je postavljen zelo visoko!</translation>
</message>
@@ -3781,10 +4042,6 @@ Opomba: Ker se provizija izračuna na bajt, bi provizija "100 satoshijev na kB"
<translation>Premalo sredstev</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Ne morete nadgraditi denarnice, ki ni ločena z HD, brez nadgradnje na podporo pred razdeljenim ključem. Uporabite -upgradewallet=169900 ali -upgradewallet brez določene različice.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Ocena provizije ni uspela. Fallbackfee je onemogočen. Počakajte nekaj blokov ali omogočite -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sn.ts b/src/qt/locale/bitcoin_sn.ts
index a4c24ce077..fa8b9cee20 100644
--- a/src/qt/locale/bitcoin_sn.ts
+++ b/src/qt/locale/bitcoin_sn.ts
@@ -175,6 +175,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -230,23 +233,7 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>Kero</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Marii</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Zita</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Chikwama</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
diff --git a/src/qt/locale/bitcoin_sq.ts b/src/qt/locale/bitcoin_sq.ts
index 3a9949488f..4fae82128d 100644
--- a/src/qt/locale/bitcoin_sq.ts
+++ b/src/qt/locale/bitcoin_sq.ts
@@ -26,10 +26,18 @@
<translation>Fshi adresen e selektuar nga lista</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>Vendos adresën ose etiketën për të kërkuar</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Eksporto të dhënat e skedës korrente në një skedar</translation>
</message>
<message>
+ <source>&amp;Export</source>
+ <translation>&amp;Eksporto</translation>
+ </message>
+ <message>
<source>&amp;Delete</source>
<translation>&amp;Fshi</translation>
</message>
@@ -164,6 +172,18 @@
<translation>Jepe fjalëkalimin e vjetër dhe fjalkalimin e ri për portofolin.</translation>
</message>
<message>
+ <source>Wallet to be encrypted</source>
+ <translation>Portofoli që duhet të enkriptohet</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Portofoli juaj do të enkriptohet</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Portofoli juaj është i enkriptuar.</translation>
+ </message>
+ <message>
<source>Wallet encryption failed</source>
<translation>Enkriptimi i portofolit dështoi</translation>
</message>
@@ -218,6 +238,10 @@
<translation>Mbyllni aplikacionin</translation>
</message>
<message>
+ <source>Show information about Qt</source>
+ <translation>Shfaq informacion rreth Qt</translation>
+ </message>
+ <message>
<source>&amp;Options...</source>
<translation>&amp;Opsione</translation>
</message>
@@ -431,6 +455,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -487,30 +514,22 @@
<source>Clear</source>
<translation>Pastro</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Nuk mund të ç'kyçet portofoli.</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>&amp;Kopjo adresen</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresë</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Sasia</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etiketë</translation>
+ <source>Amount:</source>
+ <translation>Shuma:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Portofol</translation>
+ <source>Copy &amp;Address</source>
+ <translation>&amp;Kopjo adresen</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -768,9 +787,17 @@
<context>
<name>WalletView</name>
<message>
+ <source>&amp;Export</source>
+ <translation>&amp;Eksporto</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>Eksporto të dhënat e skedës korrente në një skedar</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Problem</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_sr.ts b/src/qt/locale/bitcoin_sr.ts
index 8e511ba027..81741a5c60 100644
--- a/src/qt/locale/bitcoin_sr.ts
+++ b/src/qt/locale/bitcoin_sr.ts
@@ -70,8 +70,10 @@
<translation>Ово су твоје Биткоин адресе за слање уплата. Увек добро провери износ и адресу на коју шаљеш пре него што пошаљеш уплату.</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.</source>
- <translation>Ово су твоје Биткоин адресе за примање уплата. Користи дугме „Направи нову адресу за примање” у картици за примање за креирање нових адреса.</translation>
+ <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>Ово су твоје Биткоин адресе за приманје уплата. Користи дугме „Направи нову адресу за примање” у картици за примање за креирање нових адреса.
+Потписивање је могуђе само за адресе типа 'legacy'.</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -518,6 +520,10 @@
<translation>Затвори новчаник</translation>
</message>
<message>
+ <source>Close all wallets</source>
+ <translation>Затвори све новчанике</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Прикажи поруку помоћи %1 за листу са могућим опцијама Биткоин командне линије</translation>
</message>
@@ -625,11 +631,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Новчаник јс &lt;b&gt;шифрован&lt;/b&gt; и тренутно &lt;b&gt;закључан&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Дошло је до критичне грешке. Биткоин не може безбедно да настави са радом и искључиће се.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1135,10 +1137,6 @@
<translation>Приказује се ако је испоручени уобичајени SOCKS5 проxy коришћен ради проналажења клијената преко овог типа мреже. </translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Користи посебан SOCKS&amp;5 како би пронашли клијенте преко Тор-а.</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Сакриј икону са системске траке.</translation>
</message>
@@ -1271,10 +1269,6 @@
<translation>Тор</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Конектуј се на Биткоин мрежу кроз SOCK5 прокси за Тор скривене сервисе.</translation>
- </message>
- <message>
<source>Show only a tray icon after minimizing the window.</source>
<translation>Покажи само иконицу у панелу након минимизирања прозора</translation>
</message>
@@ -1445,7 +1439,50 @@
<source>Current total balance in watch-only addresses</source>
<translation>Тренутни укупни салдо у адресама у опцији само-гледај</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Дијалог</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Потпиши Трансакцију</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Емитуј Трансакцију</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Копирајте у клипборд.</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Сачувај...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Затвори</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Сачувај Податке Трансакције</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Парцијално Потписана Трансакција (Binary) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Укупан износ</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>или</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1705,10 +1742,6 @@
<translation>Блокчејн</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Тренутни број блокова</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Удружена меморија</translation>
</message>
@@ -1753,10 +1786,6 @@
<translation>Одабери колегу да би видели детаљне информације</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>На списку познатих</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Правац</translation>
</message>
@@ -1809,10 +1838,6 @@
<translation>Услуге</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Ниво забране</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Време конекције</translation>
</message>
@@ -1961,14 +1986,6 @@
<translation>Одлазеће</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Да</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Не</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Непознато</translation>
</message>
@@ -2067,12 +2084,32 @@
<source>Copy amount</source>
<translation>Копирај износ</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Новчаник није могуће откључати.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Код</translation>
+ <source>Address:</source>
+ <translation>Адреса:</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Износ:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Етикета</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Порука:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Новчаник:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2094,30 +2131,6 @@
<source>Payment information</source>
<translation>Информације о плаћању</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Адреса</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Износ</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Ознака</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Порука</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Новчаник</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2365,8 +2378,16 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Да ли сте сигурни да желите да пошаљете?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Молим, проверите ваш предлог трансакције. Ово ће произвести делимично потписану Биткоин трансакцију (PSBT) коју можете копирати и онда потписати са нпр. офлајн %1 новчаником, или PSBT компатибилним хардверским новчаником.</translation>
+ <source>Save Transaction Data</source>
+ <translation>Сачувај Податке Трансакције</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Делимично Потписана Трансакција (Binary) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT сачуван</translation>
</message>
<message>
<source>or</source>
@@ -2405,18 +2426,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Потврдите предлог трансакције</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Копирајте PSBT у базу за копирање</translation>
- </message>
- <message>
<source>Send</source>
<translation>Пошаљи</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT је копиран</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Само-гледање Стање:</translation>
</message>
@@ -3190,12 +3203,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Услед затварања новчаника на дугачки период времена може се десити да је потребна поновна синхронизација комплетног ланца, уколико је дозвољено резање.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Затвори све новчанике</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Да ли сигурно желите да затворите све новчанике?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Ниједан новчаник није учитан.</translation>
+ <source>Create a new wallet</source>
+ <translation>Направи нови ночаник</translation>
</message>
</context>
<context>
@@ -3268,6 +3289,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Извези податке из одабране картице у фајлj</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Грешка</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Није могуће декодирати PSBT из клипборд-а (неважећи base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Учитај Податке Трансакције</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Делимично Потписана Трансакција (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PSBT фајл мора бити мањи од 100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Немогуће декодирати PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Резервна копија новчаника</translation>
</message>
@@ -3311,10 +3356,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Скраћивање: последња синхронизација иде преко одрезаних података. Потребно је урадити ре-индексирање (преузети комплетан ланац блокова поново у случају одсеченог чвора)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Грешка: Десила се фатална интерна грешка, погледати debug.log за детаље</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Скраћивање спремљених блокова...</translation>
</message>
@@ -3327,10 +3368,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%s девелопери</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Кључ за промену адресе није могуће генерисати. У интерној групи кључева нема кључева и не може се генерисати нови кључ.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Директоријум података се не може закључати %s. %s је вероватно већ покренут.</translation>
</message>
@@ -3379,14 +3416,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Упозорење: Изгледа да се ми у потпуности не слажемо са нашим чворовима! Можда постоји потреба да урадите надоградњу, или други чворови морају да ураде надоградњу.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d од последњих 100 блокова имају неочекивану верзију</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s је оштећен, спас није успео</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool мора бити минимално %d MB</translation>
</message>
@@ -3511,10 +3540,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Учитавање P2P адреса...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Грешка: Простор на диску је сувише мали!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Учитавање листе забрана...</translation>
</message>
@@ -3591,6 +3616,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Обновите базу података користећи -reindex да би се вратили у нескраћени мод. Ово ће урадити поновно преузимање комплетног ланца података</translation>
</message>
<message>
+ <source>Disk space is too low!</source>
+ <translation>Премало простора на диску!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Грешка приликом читања из базе података, искључивање у току.</translation>
</message>
@@ -3697,10 +3726,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Упозорење: активирано је ново непознато правило (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Затварање свих трансакција из новчаника...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee је постављен сувише високо! Овако велике провизије могу бити наплаћене на само једној трансакцији.</translation>
</message>
@@ -3713,10 +3738,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Укупна дужина мрежне верзије низа (%i) је већа од максималне дужине (%i). Смањити број или величину корисничких коментара.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Упозорење: Датотека новчаника је оштећена, подаци су спасени! Оргинални %s је снимљен као %s у %s; уколико ваш салдо или трансакције нису исправни, потребно је вратити податке из резервне копије. </translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s је постављен врло високо!</translation>
</message>
@@ -3761,10 +3782,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Недовољно средстава</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>HD подељени новчаник се не може надоградити без надоградње групе кључева пре дељења. Молим користите -upgradewallet=169900 или -upgradewallet без наведене верзије.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Процена провизије није успела. Промена провизије током трансакције је онемогућена. Сачекајте неколико блокова или омогућите -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_sr@latin.ts b/src/qt/locale/bitcoin_sr@latin.ts
index 02f0fb72b5..bfed8b96ae 100644
--- a/src/qt/locale/bitcoin_sr@latin.ts
+++ b/src/qt/locale/bitcoin_sr@latin.ts
@@ -70,10 +70,6 @@
<translation>Ovo su Vaše Bitcoin adrese na koju se vrše uplate. Uvek proverite iznos i prijemnu adresu pre slanja novčića.</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.</source>
- <translation>Ovo su vaše Bitcoin adrese za primanje isplete. Upotrebite dugme 'Kreiraj novu adresu prijema' na kartici za prijem da biste kreirali nove adrese.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopiraj Adresu</translation>
</message>
@@ -549,6 +545,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -577,26 +576,14 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Kolicina</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Oznaka</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Poruka</translation>
+ <source>Amount:</source>
+ <translation>Iznos:</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Novčanik</translation>
+ <source>Wallet:</source>
+ <translation>Novčanik:</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -881,6 +868,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Izvoz podataka iz trenutne kartice u datoteku</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Greska</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_sv.ts b/src/qt/locale/bitcoin_sv.ts
index 28bb524ef0..3aa4cb9ce9 100644
--- a/src/qt/locale/bitcoin_sv.ts
+++ b/src/qt/locale/bitcoin_sv.ts
@@ -70,10 +70,6 @@
<translation>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.</source>
- <translation>Detta är dina Bitcoinadresser för att ta emot betalningar. Använd knappen 'Skapa ny mottagaradress' på fliken ta emot för att skapa nya adresser .</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Kopiera adress</translation>
</message>
@@ -630,11 +626,7 @@ Försök igen.</translation>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Denna plånbok är &lt;b&gt;krypterad&lt;/b&gt; och för närvarande &lt;b&gt;låst&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Ett kritiskt fel uppstod. Bitcoin kan inte fortsätta att köra säkert och kommer att avslutas.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1136,10 +1128,6 @@ Försök igen.</translation>
<translation>Visar om den angivna standard-SOCKS5-proxyn används för att nå noder via den här nätverkstypen.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Använd separat SOCKS&amp;5-proxy för att nå noder via Tors dolda tjänster:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Dölj ikonen från systemfältet.</translation>
</message>
@@ -1272,10 +1260,6 @@ Försök igen.</translation>
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Anslut till Bitcoin-nätverket genom en separat SOCKS5-proxy för dolda tjänster i Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Fönster</translation>
</message>
@@ -1450,7 +1434,22 @@ Försök igen.</translation>
<source>Current total balance in watch-only addresses</source>
<translation>Aktuellt totalt saldo i granska-bara adresser</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Dialog</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Totalt belopp</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>eller</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1710,10 +1709,6 @@ Försök igen.</translation>
<translation>Blockkedja</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Aktuellt antal block</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Minnespool</translation>
</message>
@@ -1758,10 +1753,6 @@ Försök igen.</translation>
<translation>Välj en klient för att se detaljerad information.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Vitlistad</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Riktning</translation>
</message>
@@ -1806,10 +1797,6 @@ Försök igen.</translation>
<translation>Tjänster</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Bannlysningspoäng</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Anslutningstid</translation>
</message>
@@ -1958,14 +1945,6 @@ Försök igen.</translation>
<translation>Utgående</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Nej</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Okänd</translation>
</message>
@@ -2060,12 +2039,28 @@ Försök igen.</translation>
<source>Copy amount</source>
<translation>Kopiera belopp</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Kunde inte låsa upp plånboken.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-kod</translation>
+ <source>Amount:</source>
+ <translation>Belopp:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Etikett:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Meddelande:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Plånbok:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2087,30 +2082,6 @@ Försök igen.</translation>
<source>Payment information</source>
<translation>Betalinformaton</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adress</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Belopp</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etikett</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Meddelande</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Plånbok</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2354,10 +2325,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Är du säker på att du vill skicka?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Pleasetransaktion, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</translation>
- </message>
- <message>
<source>or</source>
<translation>eller</translation>
</message>
@@ -2394,18 +2361,10 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Bekräfta transaktionsförslag</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Kopiera PSBT till urklipp</translation>
- </message>
- <message>
<source>Send</source>
<translation>Skicka</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT kopierad</translation>
- </message>
- <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>Mottagarens adress är ogiltig. Kontrollera igen.</translation>
</message>
@@ -3179,12 +3138,12 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Om plånboken är stängd under för lång tid och gallring är aktiverad kan hela kedjan behöva synkroniseras på nytt.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Ingen plånbok har lästs in.</translation>
+ <source>Create a new wallet</source>
+ <translation>Skapa ny plånbok</translation>
</message>
</context>
<context>
@@ -3253,6 +3212,10 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Exportera informationen i aktuell flik till en fil</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Fel</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Säkerhetskopiera Plånbok</translation>
</message>
@@ -3296,10 +3259,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Gallring: senaste plånbokssynkroniseringen ligger utanför gallrade data. Du måste använda -reindex (ladda ner hela blockkedjan igen om noden gallrats)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Fel: Ett kritiskt internt fel uppstod, se debug.log för detaljer</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Gallrar blockstore...</translation>
</message>
@@ -3312,10 +3271,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>%s-utvecklarna</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Det går inte att skapa en nyckel för växel-adress. Det finns inga nycklar i den interna nyckelpoolen och det går inte att skapa några nycklar.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Kan inte låsa datakatalogen %s. %s körs förmodligen redan.</translation>
</message>
@@ -3364,14 +3319,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Varning: Vi verkar inte helt överens med våra peers! Du kan behöva uppgradera, eller andra noder kan behöva uppgradera.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d av de senaste 100 blocken har oväntad version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s är korrupt, räddning misslyckades</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool måste vara minst %d MB</translation>
</message>
@@ -3488,10 +3435,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Läser in P2P-adresser...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Fel: Diskutrymmet är för lågt!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Läser in listan över bannlysningar …</translation>
</message>
@@ -3674,10 +3617,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Varning: okända nya regler aktiverade (versionsbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Töm plånboken på alla transaktioner...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee är väldigt högt satt! Så höga avgifter kan komma att betalas för en enstaka transaktion.</translation>
</message>
@@ -3690,10 +3629,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Total längd på strängen för nätverksversion (%i) överskrider maxlängden (%i). Minska numret eller storleken på uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Varning: Plånboksfilen var korrupt, data har räddats! Den ursprungliga %s har sparas som %s i %s. Om ditt saldo eller transaktioner är felaktiga bör du återställa från en säkerhetskopia.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s är satt väldigt högt!</translation>
</message>
@@ -3738,10 +3673,6 @@ Notera: Då avgiften beräknas per byte kommer en avgift på 50 satoshi tas ut f
<translation>Otillräckligt med bitcoins</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Kan inte uppgradera till en icke-HD delad plånbok utan att uppgradera till att stödja nyckelpoolen innan delning. Var vänlig använd -upgradewallet=169900 eller -upgradewallet utan version specificerad.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Avgiftsuppskattning misslyckades. Fallbackfee är inaktiverat. Vänta några block eller aktivera -fallbackfee.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_szl.ts b/src/qt/locale/bitcoin_szl.ts
index 3fb191c50f..489a873ceb 100644
--- a/src/qt/locale/bitcoin_szl.ts
+++ b/src/qt/locale/bitcoin_szl.ts
@@ -529,11 +529,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Portmanyj je &lt;b&gt;zaszyfrowany&lt;/b&gt; i terŏźnie &lt;b&gt;zaszperowany&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Przitrefiōł sie krytyczny feler. Bitcoin niy poradzi kōntynuować bezpiycznie i ôstanie zawrzity.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1055,10 +1051,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Skupluj sie z necym Bitcoin ze pōmocōm ôsobnego proxy SOCKS5 dlŏ necu TOR</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>Ô&amp;kno</translation>
</message>
@@ -1127,6 +1119,13 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>abo</translation>
+ </message>
+ </context>
+<context>
<name>PaymentServer</name>
<message>
<source>Payment request error</source>
@@ -1273,10 +1272,6 @@
<translation>Keta blokōw</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Terŏźniŏ wielość blokōw</translation>
- </message>
- <message>
<source>Current number of transactions</source>
<translation>Terŏźniŏ wielość transakcyji</translation>
</message>
@@ -1360,14 +1355,6 @@
<source>Outbound</source>
<translation>Wychodowy</translation>
</message>
- <message>
- <source>Yes</source>
- <translation>Ja</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Niy</translation>
- </message>
</context>
<context>
<name>ReceiveCoinsDialog</name>
@@ -1411,12 +1398,24 @@
<source>Copy amount</source>
<translation>Kopiyruj kwotã</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Niy idzie było ôdszperować portmanyja.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>Kod QR</translation>
+ <source>Amount:</source>
+ <translation>Kwota:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Wiadōmość:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Portmanyj:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -1434,30 +1433,6 @@
<source>Payment information</source>
<translation>Informacyje ô płacie</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Adresa</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Kwota</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Etyketa</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Wiadōmość</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Portmanyj</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1868,6 +1843,10 @@
<translation>Eksportuj dane z aktywnyj szkarty do zbioru</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Feler</translation>
+ </message>
+ <message>
<source>Backup Failed</source>
<translation>Backup niy podarził sie</translation>
</message>
@@ -1955,10 +1934,6 @@
<translation>Imyntnŏ dugość kety wersyje (%i) przekrŏczŏ maksymalnõ dopuszczalnõ dugość (%i). Zmyńsz wielość abo miara parametra uacomment.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Pozōr: Ôdtworzōno było dane z poprzniōnego zbioru portmanyja! Ôryginalny %s ôstoł zapisany za %s w %s; jeźli twoje saldo abo transakcyje sōm niynŏleżne winiyn żeś prziwrōcić kopijõ ibrycznõ.</translation>
- </message>
- <message>
<source>Error loading wallet %s. Duplicate -wallet filename specified.</source>
<translation>Feler w czasie wgrŏwaniŏ portmanyja %s. Podanŏ tuplowane miano zbioru w -wallet.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_ta.ts b/src/qt/locale/bitcoin_ta.ts
index 85f7db346f..d35834ef64 100644
--- a/src/qt/locale/bitcoin_ta.ts
+++ b/src/qt/locale/bitcoin_ta.ts
@@ -70,10 +70,6 @@
<translation>இவை பணம் அனுப்புவதற்கு உங்களின் பிட்காயின் முகவரிகள். பிட்காயின்களை அனுப்புவதற்கு முன் எப்பொழுதும் தொகையும் பெறுதலையும் சரிபார்க்கவும்.</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.</source>
- <translation>பிட்காயின் பெறுவதற்காக உங்கள் முகவரி இவை. புதிய முகவரிகளை உருவாக்க 'புதிய முகவரியை உருவாக்கு' என்ற பட்டனை கிளிக் செய்யவும்.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;காபி முகவரி</translation>
</message>
@@ -482,6 +478,14 @@
<translation>தேதி வரை</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>நோட் விண்டோ</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>திற நோட் பிழைத்திருத்தம் மற்றும் கண்டறியும் பணியகம்</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
<translation>முகவரிகள் அனுப்புகிறது</translation>
</message>
@@ -490,6 +494,10 @@
<translation>முகவரிகள் பெறுதல்</translation>
</message>
<message>
+ <source>Open a bitcoin: URI</source>
+ <translation>திற பிட்காயின்: URI</translation>
+ </message>
+ <message>
<source>Open Wallet</source>
<translation>வாலட்டை திற</translation>
</message>
@@ -617,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Wallet குறியாக்கப்பட்டு தற்போது பூட்டப்பட்டுள்ளது</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Wallet குறியாக்கப்பட்டு தற்போது பூட்டப்பட்டுள்ளது</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1111,10 +1115,6 @@
<translation>வழங்கப்பட்ட முன்னிருப்பு SOCKS5 ப்ராக்ஸி இந்த நெட்வொர்க் வகையின் மூலம் சகலருக்கும் சென்றால் பயன்படுத்தப்படுகிறது.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Tor மறைக்கப்பட்ட சேவைகளை வழியாக சகலரையும் அணுக தனித்த SOCKS &amp; 5 ப்ராக்ஸி பயன்படுத்தவும்</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>கணினி தட்டில் இருந்து ஐகானை மறைக்கவும்.</translation>
</message>
@@ -1247,10 +1247,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>டார் மறைக்கப்பட்ட சேவைகளை தனித்த SOCKS5 ப்ராக்ஸி மூலம் பிட்கோடு நெட்வொர்க்குடன் இணைக்கவும்.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;சாளரம்</translation>
</message>
@@ -1425,7 +1421,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>தற்போதைய மொத்த சமநிலை வாட்ச் மட்டும் முகவரிகள்</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>முழு தொகை</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>அல்லது</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1445,6 +1452,10 @@
<translation>'bitcoin: //' சரியான URI அல்ல. அதற்கு பதிலாக 'பிட்கின்:' பயன்படுத்தவும்.</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>பரிவர்த்தனை வேண்டுதலை ஏற்க இயலாது ஏனென்றால் BIP70 ஆதரவு தரவில்லை</translation>
+ </message>
+ <message>
<source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
<translation>பிப்70 இல் உள்ள பரவலான பாதுகாப்பு குறைபாடுகள் காரணமாக, வாலட்டை மாற்றுவதற்கான எந்தவொரு வணிக அறிவுறுத்தல்களும் புறக்கணிக்கப்பட வேண்டும் என்று கடுமையாக பரிந்துரைக்கப்படுகிறது.</translation>
</message>
@@ -1661,10 +1672,6 @@
<translation>தடுப்பு சங்கிலி</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>தொகுதிகள் தற்போதைய எண்</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>நினைவக குளம்</translation>
</message>
@@ -1709,10 +1716,6 @@
<translation>விரிவான தகவலைப் பார்வையிட ஒரு சகவரைத் தேர்ந்தெடுக்கவும்.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>அனுமதிக்கப்பட்டவை</translation>
- </message>
- <message>
<source>Direction</source>
<translation>திசை</translation>
</message>
@@ -1737,6 +1740,10 @@
<translation>பயனர் முகவர்</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>நோட் விண்டோ</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>தற்போதைய தரவு அடைவில் இருந்து %1 பிழைத்திருத்த பதிவு கோப்பைத் திறக்கவும். இது பெரிய பதிவு கோப்புகளை சில விநாடிகள் எடுக்கலாம்.</translation>
</message>
@@ -1753,10 +1760,6 @@
<translation>சேவைகள்</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>பான் ஸ்கோர்</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>இணைப்பு நேரம்</translation>
</message>
@@ -1905,14 +1908,6 @@
<translation>வெளி செல்லும்</translation>
</message>
<message>
- <source>Yes</source>
- <translation>ஆம்</translation>
- </message>
- <message>
- <source>No</source>
- <translation>மறு</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>அறியப்படாத</translation>
</message>
@@ -2003,12 +1998,24 @@
<source>Copy amount</source>
<translation>நகல் நகல்</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>பணப்பை திறக்க முடியவில்லை.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR குறியீடு</translation>
+ <source>Amount:</source>
+ <translation>விலை</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>செய்தி:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>கைப்பை:</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2030,30 +2037,6 @@
<source>Payment information</source>
<translation>கொடுப்பனவு தகவல்</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>முகவரி</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>தொகை</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>லேபிள்</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>செய்தி</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>பணப்பை</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2317,6 +2300,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>அனுப்பும் பிட்காயின்களை உறுதிப்படுத்தவும்</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <translation>பரிவர்த்தனை வரைவு உறுதி செய்</translation>
+ </message>
+ <message>
+ <source>Send</source>
+ <translation>அனுப்புவும்</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
<translation>பெறுநரின் முகவரி தவறானது. மீண்டும் சரிபார்க்கவும்.</translation>
</message>
@@ -2558,6 +2549,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>வாலட் திறத்தல் ரத்து செய்யப்பட்டது.</translation>
</message>
<message>
+ <source>No error</source>
+ <translation>தவறு எதுவுமில்லை</translation>
+ </message>
+ <message>
<source>Private key for the entered address is not available.</source>
<translation>உள்ளிட்ட முகவரிக்கான ப்ரைவேட் கீ கிடைக்கவில்லை.</translation>
</message>
@@ -3042,12 +3037,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>வாலட்டை அதிக நேரம் மூடுவதாலும் ப்ரூனிங் இயக்கப்பட்டாலோ முழு செயினை ரீசிங்க் செய்வதற்கு இது வழிவகுக்கும்.</translation>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>எந்த வாலட்டும் லோட் செய்யப்படவில்லை.</translation>
+ <source>Create a new wallet</source>
+ <translation>புதிய வாலட்டை உருவாக்கு</translation>
</message>
</context>
<context>
@@ -3085,6 +3080,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>கட்டண ஏற்றத்தை உறுதிப்படுத்தவும்</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>பரிவர்த்தனை செய்ய இயலாது</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>பரிவர்த்தனையில் கையொப்பமிட முடியவில்லை.</translation>
</message>
@@ -3108,6 +3107,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>தற்போதைய தாவலில் தரவை ஒரு கோப்பிற்கு ஏற்றுமதி செய்க</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>பிழை</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>பேக்அப் வாலட்</translation>
</message>
@@ -3151,10 +3154,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>ப்ரூன்: கடைசி வாலட் ஒத்திசைவு ப்ரூன் தரவுக்கு அப்பாற்பட்டது. நீங்கள் -reindex செய்ய வேண்டும் (ப்ரூன் நோட் உபயோகித்தால் முழு பிளாக்செயினையும் மீண்டும் டவுன்லோட் செய்யவும்)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>பிழை: ஆபத்தான உள் பிழை ஏற்பட்டது, விவரங்களுக்கு debug.log ஐ பார்க்கவும்</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>பிளாக்ஸ்டோர் ப்ரூன் செய்யபடுகிறது...</translation>
</message>
@@ -3167,10 +3166,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%s டெவலப்பர்கள்</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>மாற்று-முகவரி கீயை உருவாக்க முடியாது. கீ தகவல்தளத்தில் கீகள் இல்லை மற்றும் எந்த கீயையும் உருவாக்க முடியாது.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>தரவு கோப்பகத்தை %s லாக் செய்ய முடியாது. %s ஏற்கனவே இயங்குகிறது.</translation>
</message>
@@ -3219,14 +3214,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>எச்சரிக்கை: நாங்கள் எங்கள் பீர்களுடன் முழுமையாக உடன்படுவதாகத் தெரியவில்லை! நீங்கள் அப்க்ரேட் செய்ய வேண்டியிருக்கலாம், அல்லது மற்ற நோடுகள் அப்க்ரேட் செய்ய வேண்டியிருக்கலாம்.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>கடைசி 100 தொகுதிகளில் %d எதிர்பாராத பதிப்பைக் கொண்டுள்ளன</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s சிதைந்தது, மீட்பு தோல்வியுற்றது</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-மேக்ஸ்மெம்பூல் குறைந்தது %d எம்பி ஆக இருக்க வேண்டும்</translation>
</message>
@@ -3331,10 +3318,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>பி2பி முகவரிகள் லோட் செய்யப்படுகிறது...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>பிழை: டிஸ்க் ஸ்பேஸ் மிகக் குறைவாக உள்ளது!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>தடைப்பட்டியல் லோட் செய்யப்படுகிறது...</translation>
</message>
@@ -3467,10 +3450,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>எச்சரிக்கை: அறியப்படாத புதிய விதிகள் செயல்படுத்தப்பட்டன (வெர்ஷன்பிட் %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>வாலாட்டிலிருந்து அனைத்து பரிவர்த்தனைகளையும் அழிக்கிறது...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee மிக அதிகமாக அமைக்கப்பட்டுள்ளது! இவ்வாறு அதிகமுள்ள கட்டணம் ஒரே பரிவர்த்தனையில் செலுத்தப்படலாம்.</translation>
</message>
diff --git a/src/qt/locale/bitcoin_te.ts b/src/qt/locale/bitcoin_te.ts
index 1e057d15bc..515e82c54a 100644
--- a/src/qt/locale/bitcoin_te.ts
+++ b/src/qt/locale/bitcoin_te.ts
@@ -70,10 +70,6 @@
<translation>ఇవి మీరు పంపే చెల్లింపుల బిట్‌కాయిన్ చిరునామాలు. నాణేలు పంపే ముందు ప్రతిసారి అందుకునే చిరునామా మరియు చెల్లింపు మొత్తం సరిచూసుకోండి.</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.</source>
- <translation>చెల్లింపులు స్వీకరించడానికి ఇవి మీ బిట్‌కాయిన్ చిరునామాలు. క్రొత్త చిరునామాలను సృష్టించడానికి స్వీకరించు ట్యాబ్‌లోని 'క్రొత్త స్వీకరించే చిరునామాను సృష్టించండి' బటన్‌ను ఉపయోగించండి.</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>చిరునామాను కాపీ చెయ్యండి</translation>
</message>
@@ -303,6 +299,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -326,23 +325,7 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>చిరునామా</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>ఉల్లాకు</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>సందేశం</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>వాలెట్</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -483,6 +466,10 @@
<source>Export the data in the current tab to a file</source>
<translation>ప్రస్తుతం ఉన్న సమాచారాన్ని ఫైల్ లోనికి ఎగుమతి చేసుకోండి</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>లోపం</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_th.ts b/src/qt/locale/bitcoin_th.ts
index 4d82f7949b..3da787dfb4 100644
--- a/src/qt/locale/bitcoin_th.ts
+++ b/src/qt/locale/bitcoin_th.ts
@@ -70,10 +70,6 @@
<translation>ที่อยู่ 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.</source>
- <translation>นี่คือที่อยู่สำหรับการรับ Bitcoin ของคุณ กดปุ่ม ‘สร้างที่อยู่การรับใหม่’ ในแถบการรับ เพื่อสร้างที่อยู่การรับใหม่</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>คัดลอกที่อยู่</translation>
</message>
@@ -447,11 +443,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>กระเป๋าเงินถูก &lt;b&gt;เข้ารหัส&lt;/b&gt; และในปัจจุบัน &lt;b&gt;ล็อค &lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>เกิดข้อผิดพลาดร้ายแรง Bitcoin ไม่สามารถดำเนินการต่อได้อย่างปลอดภัยอีกต่อไปและจะยกเลิก</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -809,10 +801,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>เชื่อมต่อกับ เครือข่าย Bitcoin ผ่านทาง พร้อกซี่ SOCKS5 แยกต่างหาก สำหรับ Tor เซอร์วิส</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;วันโดว์</translation>
</message>
@@ -833,6 +821,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -869,26 +860,14 @@
<source>Copy amount</source>
<translation>คัดลอกจำนวนเงิน</translation>
</message>
-</context>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>ที่อยู่</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>จำนวน</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>ฉลาก, ป้าย,</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>กระเป๋าเงิน</translation>
+ <source>Amount:</source>
+ <translation>จำนวน:</translation>
</message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -1061,6 +1040,10 @@
<source>Export the data in the current tab to a file</source>
<translation>ส่งออกข้อมูลที่อยู่ในแถบนี้ไปในไฟล์</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>ข้อผิดพลาด</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_tr.ts b/src/qt/locale/bitcoin_tr.ts
new file mode 100644
index 0000000000..e2c28fca7c
--- /dev/null
+++ b/src/qt/locale/bitcoin_tr.ts
@@ -0,0 +1,919 @@
+<TS language="tr" version="2.1">
+<context>
+ <name>AddressBookPage</name>
+ <message>
+ <source>Right-click to edit address or label</source>
+ <translation>Adres veya etiketi düzenlemek için sağ tıklayın</translation>
+ </message>
+ <message>
+ <source>Create a new address</source>
+ <translation>Yeni adres oluşturun</translation>
+ </message>
+ <message>
+ <source>&amp;New</source>
+ <translation>Yeni</translation>
+ </message>
+ <message>
+ <source>Copy the currently selected address to the system clipboard</source>
+ <translation>Seçili adresi panoya kopyalayın</translation>
+ </message>
+ <message>
+ <source>&amp;Copy</source>
+ <translation>Kopyala</translation>
+ </message>
+ <message>
+ <source>C&amp;lose</source>
+ <translation>Kapat</translation>
+ </message>
+ <message>
+ <source>Delete the currently selected address from the list</source>
+ <translation>Seçili adesi listeden silin</translation>
+ </message>
+ <message>
+ <source>Enter address or label to search</source>
+ <translation>Aramak için adres veya etiket girin</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Geçerli sekmedeki veriyi bir dosyaya dışa aktarın</translation>
+ </message>
+ <message>
+ <source>&amp;Export</source>
+ <translation>Dışa aktar</translation>
+ </message>
+ <message>
+ <source>&amp;Delete</source>
+ <translation>Sil</translation>
+ </message>
+ <message>
+ <source>Choose the address to send coins to</source>
+ <translation>Coin gönderilecek adresi seçiniz</translation>
+ </message>
+ <message>
+ <source>C&amp;hoose</source>
+ <translation>S&amp;ç</translation>
+ </message>
+ <message>
+ <source>Sending addresses</source>
+ <translation>Gönderici adresler</translation>
+ </message>
+ <message>
+ <source>Receiving addresses</source>
+ <translation>Alıcı adresler</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>Bunlar Bitcoinleriniz için gönderici adreslerinizdir.
+Gönderim yapmadan önce her zaman tutarı ve alıcı adresi kontrol ediniz.</translation>
+ </message>
+ <message>
+ <source>&amp;Copy Address</source>
+ <translation>Adresi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy &amp;Label</source>
+ <translation>Etiketi kopyala</translation>
+ </message>
+ <message>
+ <source>&amp;Edit</source>
+ <translation>Düzenle</translation>
+ </message>
+ <message>
+ <source>Export Address List</source>
+ <translation>Adres Listesini Dışa Aktar</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Virgülle ayrılmış dosya (*.csv)</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Dışa Aktarım Başarısız Oldu</translation>
+ </message>
+ </context>
+<context>
+ <name>AddressTableModel</name>
+ <message>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>ADres</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(etiket yok)</translation>
+ </message>
+</context>
+<context>
+ <name>AskPassphraseDialog</name>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>Parolanızı giriniz.</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>Yeni parola</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>Yeni parolanızı tekrar ediniz</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation>Parolayı göster</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>Cüzdan şifrele</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>Bu işlemi yapabilmek için cüzdan parolanızı girmeniz gerekmektedir
+Cüzdan kilidini aç.</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>Cüzdan kilidini aç</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>cüzdan şifresini çöz</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>Parola değiştir</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>Cüzdan şifrelemeyi onayla</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to encrypt your wallet?</source>
+ <translation>Cüzdanınızı şifrelemek istediğinizden emin misiniz?</translation>
+ </message>
+ <message>
+ <source>Wallet encrypted</source>
+ <translation>Cüzdan şifrelendi</translation>
+ </message>
+ <message>
+ <source>Your wallet is about to be encrypted. </source>
+ <translation>Cüzdanınız şifrelenmek üzere</translation>
+ </message>
+ <message>
+ <source>Your wallet is now encrypted. </source>
+ <translation>Cüzdanınız şu an şifrelenmiş</translation>
+ </message>
+ <message>
+ <source>Wallet encryption failed</source>
+ <translation>Cüzdan şifreleme başarısız oldu</translation>
+ </message>
+ <message>
+ <source>Wallet unlock failed</source>
+ <translation>Cüzdan kilidi açma başarız oldu</translation>
+ </message>
+ <message>
+ <source>Wallet passphrase was successfully changed.</source>
+ <translation>Cüzdan parolası başarılı bir şekilde değiştirildi</translation>
+ </message>
+ <message>
+ <source>Warning: The Caps Lock key is on!</source>
+ <translation>Uyarı: Caps lock açık</translation>
+ </message>
+</context>
+<context>
+ <name>BanTableModel</name>
+ <message>
+ <source>IP/Netmask</source>
+ <translation>İP/Ağ maskesi</translation>
+ </message>
+ <message>
+ <source>Banned Until</source>
+ <translation>Kadar Yasaklı</translation>
+ </message>
+</context>
+<context>
+ <name>BitcoinGUI</name>
+ <message>
+ <source>Sign &amp;message...</source>
+ <translation>&amp;Mesajı imzala ...</translation>
+ </message>
+ <message>
+ <source>Synchronizing with network...</source>
+ <translation>Ağ ile senkronize ediliyor...</translation>
+ </message>
+ <message>
+ <source>&amp;Overview</source>
+ <translation>Genel durum</translation>
+ </message>
+ <message>
+ <source>Show general overview of wallet</source>
+ <translation>Cüzdan genel durumunu göster</translation>
+ </message>
+ <message>
+ <source>&amp;Transactions</source>
+ <translation>İşlemler</translation>
+ </message>
+ <message>
+ <source>Browse transaction history</source>
+ <translation>İşlem geçişini görüntüle</translation>
+ </message>
+ <message>
+ <source>E&amp;xit</source>
+ <translation>Çıkış</translation>
+ </message>
+ <message>
+ <source>Quit application</source>
+ <translation>Uygulamayı kapat</translation>
+ </message>
+ <message>
+ <source>Show information about %1</source>
+ <translation>%1 hakkındaki bilgileri göster</translation>
+ </message>
+ <message>
+ <source>About &amp;Qt</source>
+ <translation>&amp;Qt hakkında</translation>
+ </message>
+ <message>
+ <source>Show information about Qt</source>
+ <translation>Qt hakkındaki bilgileri göster</translation>
+ </message>
+ <message>
+ <source>&amp;Options...</source>
+ <translation>Seçenekler</translation>
+ </message>
+ <message>
+ <source>Modify configuration options for %1</source>
+ <translation>%1 için yapılandırma seçeneklerini değiştirin</translation>
+ </message>
+ <message>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>Cüzdan &amp;Şifrelemek...</translation>
+ </message>
+ <message>
+ <source>&amp;Backup Wallet...</source>
+ <translation>Cüzdanı &amp;Yedekle</translation>
+ </message>
+ <message>
+ <source>&amp;Change Passphrase...</source>
+ <translation>Parola &amp;Değiştir...</translation>
+ </message>
+ <message>
+ <source>Open &amp;URI...</source>
+ <translation>&amp;URI aç...</translation>
+ </message>
+ <message>
+ <source>Create Wallet...</source>
+ <translation>Cüzdan oluştur</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Yeni bir cüzdan oluştur</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Cüzdan</translation>
+ </message>
+ <message>
+ <source>Click to disable network activity.</source>
+ <translation>Ağ etkinliğini devre dışı bırakmak için tıklayın.</translation>
+ </message>
+ <message>
+ <source>Network activity disabled.</source>
+ <translation>Network aktivitesi devre dışı bırakıldı</translation>
+ </message>
+ <message>
+ <source>Click to enable network activity again.</source>
+ <translation>Network activitesini serbest bırakmak için tıklayınız</translation>
+ </message>
+ <message>
+ <source>Syncing Headers (%1%)...</source>
+ <translation>Bağlantılar senkronize ediliyor (%1%)...</translation>
+ </message>
+ <message>
+ <source>Reindexing blocks on disk...</source>
+ <translation>Diskteki blokları yeniden indeksleme ...</translation>
+ </message>
+ <message>
+ <source>&amp;Verify message...</source>
+ <translation>Mesajı doğrula</translation>
+ </message>
+ <message>
+ <source>&amp;Send</source>
+ <translation>Gönder</translation>
+ </message>
+ <message>
+ <source>&amp;Receive</source>
+ <translation>&amp;Teslim alınan</translation>
+ </message>
+ <message>
+ <source>&amp;Show / Hide</source>
+ <translation>Göster / Gizle</translation>
+ </message>
+ <message>
+ <source>Show or hide the main Window</source>
+ <translation>Ana pencereyi göster ve ya gizle</translation>
+ </message>
+ <message>
+ <source>&amp;File</source>
+ <translation>Dosya</translation>
+ </message>
+ <message>
+ <source>&amp;Settings</source>
+ <translation>Ayarlar</translation>
+ </message>
+ <message>
+ <source>&amp;Help</source>
+ <translation>Yardım</translation>
+ </message>
+ <message>
+ <source>Tabs toolbar</source>
+ <translation>Araç çubuğu sekmeleri</translation>
+ </message>
+ <message>
+ <source>&amp;Command-line options</source>
+ <translation>Komut-satırı seçenekleri</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hata</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Uyarı</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Bilgi</translation>
+ </message>
+ <message>
+ <source>Up to date</source>
+ <translation>Güncel</translation>
+ </message>
+ <message>
+ <source>Open Wallet</source>
+ <translation>Cüzdanı aç</translation>
+ </message>
+ <message>
+ <source>Open a wallet</source>
+ <translation>Bir cüzdan aç</translation>
+ </message>
+ <message>
+ <source>Close Wallet...</source>
+ <translation>Çüzdan kapat</translation>
+ </message>
+ <message>
+ <source>Close wallet</source>
+ <translation>Cüzdan kapat</translation>
+ </message>
+ <message>
+ <source>default wallet</source>
+ <translation>Varsayılan cüzdan</translation>
+ </message>
+ <message>
+ <source>No wallets available</source>
+ <translation>Erişilebilir cüzdan yok</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>Pencere</translation>
+ </message>
+ <message>
+ <source>Minimize</source>
+ <translation>Küçült</translation>
+ </message>
+ <message>
+ <source>Zoom</source>
+ <translation>Yakınlaştır</translation>
+ </message>
+ <message>
+ <source>Main Window</source>
+ <translation>Ana Pencere</translation>
+ </message>
+ </context>
+<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <source>Quantity:</source>
+ <translation>Miktar</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Miktar</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Ücret</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Değiştir</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Mitar</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Copy address</source>
+ <translation>Adresi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Etiketi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Miktar kopyala</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>İşlem numarasını kopyala</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Miktarı kopyala</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Ücreti kopyala</translation>
+ </message>
+ <message>
+ <source>yes</source>
+ <translation>evet</translation>
+ </message>
+ <message>
+ <source>no</source>
+ <translation>hayır</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(etiket yok)</translation>
+ </message>
+ <message>
+ <source>(change)</source>
+ <translation>(değiştir)</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletActivity</name>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>Cüzdan oluşturma uyarısı</translation>
+ </message>
+</context>
+<context>
+ <name>CreateWalletDialog</name>
+ <message>
+ <source>Create Wallet</source>
+ <translation>Cüzdan oluştur</translation>
+ </message>
+ <message>
+ <source>Wallet Name</source>
+ <translation>Cüzdan ismi</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>Cüzdanı şifrele</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>Oluştur</translation>
+ </message>
+</context>
+<context>
+ <name>EditAddressDialog</name>
+ <message>
+ <source>Edit Address</source>
+ <translation>Adresi düzenle</translation>
+ </message>
+ <message>
+ <source>&amp;Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>&amp;Address</source>
+ <translation>Adres</translation>
+ </message>
+ </context>
+<context>
+ <name>FreespaceChecker</name>
+ <message>
+ <source>name</source>
+ <translation>İsim</translation>
+ </message>
+ </context>
+<context>
+ <name>HelpMessageDialog</name>
+ <message>
+ <source>version</source>
+ <translation>Versiyon</translation>
+ </message>
+ <message>
+ <source>Command-line options</source>
+ <translation>Komut-satırı seçenekleri</translation>
+ </message>
+</context>
+<context>
+ <name>Intro</name>
+ <message>
+ <source>Welcome</source>
+ <translation>Hoş geldiniz </translation>
+ </message>
+ <message>
+ <source>Bitcoin</source>
+ <translation>Bitcoin</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hata</translation>
+ </message>
+ </context>
+<context>
+ <name>ModalOverlay</name>
+ <message>
+ <source>Unknown...</source>
+ <translation>Bilinmeyen</translation>
+ </message>
+ <message>
+ <source>calculating...</source>
+ <translation>Hesaplanıyor</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Gizle</translation>
+ </message>
+ </context>
+<context>
+ <name>OpenURIDialog</name>
+ </context>
+<context>
+ <name>OpenWalletActivity</name>
+ <message>
+ <source>default wallet</source>
+ <translation>Varsayılan cüzdan</translation>
+ </message>
+ </context>
+<context>
+ <name>OptionsDialog</name>
+ <message>
+ <source>Options</source>
+ <translation>Seçenekler</translation>
+ </message>
+ <message>
+ <source>Proxy &amp;IP:</source>
+ <translation>Proxy &amp;IP:</translation>
+ </message>
+ <message>
+ <source>IPv4</source>
+ <translation>IPv4</translation>
+ </message>
+ <message>
+ <source>IPv6</source>
+ <translation>IPv6</translation>
+ </message>
+ <message>
+ <source>&amp;Window</source>
+ <translation>Pencere</translation>
+ </message>
+ <message>
+ <source>&amp;OK</source>
+ <translation>Tamam</translation>
+ </message>
+ <message>
+ <source>&amp;Cancel</source>
+ <translation>İptal</translation>
+ </message>
+ <message>
+ <source>default</source>
+ <translation>Varsayılan</translation>
+ </message>
+ <message>
+ <source>none</source>
+ <translation>hiçbiri</translation>
+ </message>
+ <message>
+ <source>Confirm options reset</source>
+ <translation>Seçenekleri sıfırlamayı onayla</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hata</translation>
+ </message>
+ </context>
+<context>
+ <name>OverviewPage</name>
+ <message>
+ <source>Balances</source>
+ <translation>Hesaplar</translation>
+ </message>
+ <message>
+ <source>Total:</source>
+ <translation>Toplam</translation>
+ </message>
+ <message>
+ <source>Spendable:</source>
+ <translation>Harcanabilir</translation>
+ </message>
+ <message>
+ <source>Recent transactions</source>
+ <translation>Yakın zamandaki işlemler</translation>
+ </message>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Diyalog</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>veya</translation>
+ </message>
+ </context>
+<context>
+ <name>PaymentServer</name>
+ <message>
+ <source>Payment request error</source>
+ <translation>Ödeme isteği hatası</translation>
+ </message>
+ </context>
+<context>
+ <name>PeerTableModel</name>
+ <message>
+ <source>Sent</source>
+ <translation>Gönderildi</translation>
+ </message>
+ </context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Amount</source>
+ <translation>Mitar</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>bilinmeyen</translation>
+ </message>
+</context>
+<context>
+ <name>QRImageWidget</name>
+ <message>
+ <source>Save QR Code</source>
+ <translation>QR kodu kaydet</translation>
+ </message>
+ </context>
+<context>
+ <name>RPCConsole</name>
+ <message>
+ <source>Name</source>
+ <translation>isim</translation>
+ </message>
+ <message>
+ <source>Memory usage</source>
+ <translation>Bellek kullanımı</translation>
+ </message>
+ <message>
+ <source>Wallet: </source>
+ <translation>Cüzdan</translation>
+ </message>
+ <message>
+ <source>Sent</source>
+ <translation>Gönderildi</translation>
+ </message>
+ <message>
+ <source>Version</source>
+ <translation>Versiyon</translation>
+ </message>
+ <message>
+ <source>Services</source>
+ <translation>Servisler</translation>
+ </message>
+ <message>
+ <source>never</source>
+ <translation>Hiçbir zaman </translation>
+ </message>
+ <message>
+ <source>Unknown</source>
+ <translation>Bilinmeyen</translation>
+ </message>
+</context>
+<context>
+ <name>ReceiveCoinsDialog</name>
+ <message>
+ <source>Copy label</source>
+ <translation>Etiketi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Miktar kopyala</translation>
+ </message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Cüzdan kilidi açılamadı.</translation>
+ </message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
+ <message>
+ <source>Amount:</source>
+ <translation>Tutar:</translation>
+ </message>
+ <message>
+ <source>Label:</source>
+ <translation>Etiket:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>İleti:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Cüzdan</translation>
+ </message>
+ </context>
+<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(etiket yok)</translation>
+ </message>
+ </context>
+<context>
+ <name>SendCoinsDialog</name>
+ <message>
+ <source>Quantity:</source>
+ <translation>Miktar</translation>
+ </message>
+ <message>
+ <source>Amount:</source>
+ <translation>Miktar</translation>
+ </message>
+ <message>
+ <source>Fee:</source>
+ <translation>Ücret</translation>
+ </message>
+ <message>
+ <source>Change:</source>
+ <translation>Değiştir</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Gizle</translation>
+ </message>
+ <message>
+ <source>Copy quantity</source>
+ <translation>Miktarı kopyala</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Miktar kopyala</translation>
+ </message>
+ <message>
+ <source>Copy fee</source>
+ <translation>Ücreti kopyala</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(etiket yok)</translation>
+ </message>
+</context>
+<context>
+ <name>SendCoinsEntry</name>
+ </context>
+<context>
+ <name>ShutdownWindow</name>
+ </context>
+<context>
+ <name>SignVerifyMessageDialog</name>
+ </context>
+<context>
+ <name>TrafficGraphWidget</name>
+ </context>
+<context>
+ <name>TransactionDesc</name>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>unknown</source>
+ <translation>bilinmeyen</translation>
+ </message>
+ <message>
+ <source>Amount</source>
+ <translation>Mitar</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionDescDialog</name>
+ </context>
+<context>
+ <name>TransactionTableModel</name>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>(no label)</source>
+ <translation>(etiket yok)</translation>
+ </message>
+ </context>
+<context>
+ <name>TransactionView</name>
+ <message>
+ <source>Copy address</source>
+ <translation>Adresi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy label</source>
+ <translation>Etiketi kopyala</translation>
+ </message>
+ <message>
+ <source>Copy amount</source>
+ <translation>Miktar kopyala</translation>
+ </message>
+ <message>
+ <source>Copy transaction ID</source>
+ <translation>İşlem numarasını kopyala</translation>
+ </message>
+ <message>
+ <source>Comma separated file (*.csv)</source>
+ <translation>Virgülle ayrılmış dosya (*.csv)</translation>
+ </message>
+ <message>
+ <source>Date</source>
+ <translation>Tarih</translation>
+ </message>
+ <message>
+ <source>Label</source>
+ <translation>Etiket</translation>
+ </message>
+ <message>
+ <source>Address</source>
+ <translation>ADres</translation>
+ </message>
+ <message>
+ <source>Exporting Failed</source>
+ <translation>Dışa Aktarım Başarısız Oldu</translation>
+ </message>
+ </context>
+<context>
+ <name>UnitDisplayStatusBarControl</name>
+ </context>
+<context>
+ <name>WalletController</name>
+ <message>
+ <source>Close wallet</source>
+ <translation>Cüzdan kapat</translation>
+ </message>
+ </context>
+<context>
+ <name>WalletFrame</name>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Yeni bir cüzdan oluştur</translation>
+ </message>
+</context>
+<context>
+ <name>WalletModel</name>
+ <message>
+ <source>default wallet</source>
+ <translation>Varsayılan cüzdan</translation>
+ </message>
+</context>
+<context>
+ <name>WalletView</name>
+ <message>
+ <source>&amp;Export</source>
+ <translation>Dışa aktar</translation>
+ </message>
+ <message>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Geçerli sekmedeki veriyi bir dosyaya dışa aktarın</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Hata</translation>
+ </message>
+ </context>
+<context>
+ <name>bitcoin-core</name>
+ </context>
+</TS> \ No newline at end of file
diff --git a/src/qt/locale/bitcoin_uk.ts b/src/qt/locale/bitcoin_uk.ts
index 722daadafe..87264deea8 100644
--- a/src/qt/locale/bitcoin_uk.ts
+++ b/src/qt/locale/bitcoin_uk.ts
@@ -39,7 +39,7 @@
</message>
<message>
<source>&amp;Export</source>
- <translation>&amp;Экспорт</translation>
+ <translation>&amp;Експортувати</translation>
</message>
<message>
<source>&amp;Delete</source>
@@ -70,8 +70,10 @@
<translation>Це ваші адреси 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.</source>
- <translation>Це ваші біткойн-адреси для отримання платежів. Використовуйте кнопку "Створити нову адресу прийому" на вкладці отримання, для створення нових адрес.</translation>
+ <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>Це ваші Біткойн адреси для отримання платежів. Використовуйте кнопку "Створити нову адресу для отримання" на вкладці отримання, щоб створити нові адреси.
+Підпис можливий лише з адресами типу "legacy".</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -91,7 +93,7 @@
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Файли (*.csv) розділеі комами</translation>
+ <translation>Файли (*.csv) розділені комами</translation>
</message>
<message>
<source>Exporting Failed</source>
@@ -181,7 +183,7 @@
</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>Введіть новий пароль для гаманця.&lt;br/&gt; Будь ласка, використовуйте парол з &lt;b&gt;десяти або більше випадкових символів&lt;/b&gt;, або &lt;b&gt; вісім або більше слів&lt;/b&gt;.</translation>
+ <translation>Введіть новий пароль для гаманця.&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>
@@ -399,11 +401,11 @@
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>Підтвердіть, що Ви є власником повідомлення підписавши його Вашою Bitcoin-адресою</translation>
+ <translation>Підтвердіть, що Ви є власником повідомлення підписавши його Вашою Біткойн адресою</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>Перевірте повідомлення для впевненості, що воно підписано вказаною Bitcoin-адресою</translation>
+ <translation>Перевірте повідомлення для впевненості, що воно підписано вказаною Біткойн адресою</translation>
</message>
<message>
<source>&amp;File</source>
@@ -482,6 +484,22 @@
<translation>Синхронізовано</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>&amp;Завантажити PSBT з файлу...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>Завантажте Частково Підписану Транзакцію Біткойн</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>Скопіювати PSBT у буфер обміну</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>Завантажте Частково Підписану Біткойн Транзакцію з буфера обміну</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>Вікно вузлів</translation>
</message>
@@ -511,19 +529,35 @@
</message>
<message>
<source>Close Wallet...</source>
- <translation>закрити Гаманець ...</translation>
+ <translation>Закрити Гаманець ...</translation>
</message>
<message>
<source>Close wallet</source>
<translation>Закрити гаманець</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>Закрити Всі Гаманці...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Закрити всі гаманці</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>Показати довідку %1 для отримання переліку можливих параметрів командного рядка.</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&amp;Значення маски</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>Маскуйте значення на вкладці Огляд</translation>
+ </message>
+ <message>
<source>default wallet</source>
- <translation>гаманець за змовчуванням</translation>
+ <translation>типовий гаманець</translation>
</message>
<message>
<source>No wallets available</source>
@@ -630,8 +664,12 @@
<translation>&lt;b&gt;Зашифрований&lt;/b&gt; гаманець &lt;b&gt;заблоковано&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Сталася фатальна помилка. Гаманець буде закрито.</translation>
+ <source>Original message:</source>
+ <translation>Первинне повідомлення:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>Сталася фатальна помилка. %1 більше не може продовжувати безпечно і вийде.</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>Створити пустий гаманець</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>Використовуйте дескриптори для управління scriptPubKey</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>Дешифрування гаманця</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>Створити</translation>
</message>
@@ -936,7 +982,7 @@
<name>Intro</name>
<message>
<source>Welcome</source>
- <translation>Добро пожаловать</translation>
+ <translation>Ласкаво просимо</translation>
</message>
<message>
<source>Welcome to %1.</source>
@@ -1093,7 +1139,7 @@
</message>
<message>
<source>default wallet</source>
- <translation>гаманець за змовчуванням</translation>
+ <translation>типовий гаманець</translation>
</message>
<message>
<source>Opening Wallet &lt;b&gt;%1&lt;/b&gt;...</source>
@@ -1135,10 +1181,6 @@
<translation>Показує, чи типово використовується проксі SOCKS5 для досягнення рівної участі для цього типу мережі.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Використовуйте окремі проксі-сервери SOCKS&amp;5 для підключення до вузлів через приховані сервіси Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Приховати значок із системного лотка.</translation>
</message>
@@ -1271,10 +1313,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Підключатися до мережі Bitcoin через окремий SOCKS5 проксі для прихованих сервісів Tor.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Вікно</translation>
</message>
@@ -1315,6 +1353,14 @@
<translation>Показати або сховати керування входами.</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>Підключіться до мережі Біткойн через окремий проксі-сервер SOCKS5 для сервісів Tor.</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>Використовуйте окремий проксі-сервер SOCKS&amp;5, щоб дістатися до вузлів через послуги Tor:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>&amp;URL-адреси транзакцій сторонніх розробників</translation>
</message>
@@ -1449,6 +1495,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>Поточний сукупний баланс в адресах для спостереження</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>Режим конфіденційності активований для вкладки Огляд. Щоб демаскувати значення, зніміть прапорець Параметри-&gt; Маскувати значення.</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>Діалог</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>Знак Tx</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>Трансляція Tx</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>Копіювати у буфер обміну</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>Зберегти...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>Завершити</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>Не вдалося завантажити транзакцію: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>Не вдалося підписати транзакцію: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>Не вдалося підписати більше входів.</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>Підписано %1 введення, але все одно потрібно більше підписів.</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>Угода успішно підписана. Транзакція готова до трансляції.</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>Невідома помилка обробки транзакції.</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>Трансакція успішно транслюється! Ідентифікатор транзакції: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>Помилка трансляції транзакції: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT скопійовано в буфер обміну.</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Зберегти дані транзакції</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Частково підписана транзакція (Binary) (* .psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT збережено на диск.</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation>* Надсилає від %1 до %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>Неможливо розрахувати комісію за транзакцію або загальну суму транзакції.</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>Оплачує комісію за транзакцію:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>Всього</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>або</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>Транзакція містить %1 непідписаних входів.</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>У транзакції бракує певної інформації про вхідні дані.</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>Для транзакції все ще потрібні підпис(и).</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(Але цей гаманець не може підписувати транзакції.)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(Але цей гаманець не має правильних ключів.)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>Транзакція повністю підписана і готова до трансляції.</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>Статус транзакції невідомий.</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1528,7 +1701,7 @@
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>Введіть адресу Bitcoin (наприклад %1)</translation>
+ <translation>Введіть адресу Біткойн (наприклад %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1615,6 +1788,10 @@
<translation>Помилка: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>Помилка ініціалізації налаштувань: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 безпечний вихід ще не виконано...</translation>
</message>
@@ -1713,10 +1890,6 @@
<translation>Ланцюг блоків</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Поточне число блоків</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Пул пам'яті</translation>
</message>
@@ -1761,10 +1934,6 @@
<translation>Виберіть учасника для перегляду детальнішої інформації</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>В білому списку</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Напрямок</translation>
</message>
@@ -1801,6 +1970,10 @@
<translation>Вікно вузлів</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>Поточна висота блоку</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>Відкрийте файл журналу налагодження %1 з поточного каталогу даних. Це може зайняти кілька секунд для файлів великого розміру.</translation>
</message>
@@ -1813,12 +1986,12 @@
<translation>Збільшити розмір шрифту</translation>
</message>
<message>
- <source>Services</source>
- <translation>Сервіси</translation>
+ <source>Permissions</source>
+ <translation>Дозволи</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Очки бану</translation>
+ <source>Services</source>
+ <translation>Сервіси</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1969,14 +2142,6 @@
<translation>Вихідний</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Так</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Ні</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Невідома</translation>
</message>
@@ -2075,56 +2240,60 @@
<source>Copy amount</source>
<translation>Копіювати суму</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Неможливо розблокувати гаманець.</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>Не можливо згенерувати нову %1 адресу</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR-Код</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>&amp;Скопіювати URI</translation>
+ <source>Request payment to ...</source>
+ <translation>Запит на оплату до ...</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>Скопіювати &amp;адресу</translation>
+ <source>Address:</source>
+ <translation>Адреса:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>&amp;Зберегти зображення...</translation>
+ <source>Amount:</source>
+ <translation>Сума:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>Запит платежу на %1</translation>
+ <source>Label:</source>
+ <translation>Мітка:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>Інформація про платіж</translation>
+ <source>Message:</source>
+ <translation>Повідомлення:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>Гаманець:</translation>
</message>
<message>
- <source>Address</source>
- <translation>Адрес</translation>
+ <source>Copy &amp;URI</source>
+ <translation>&amp;Скопіювати URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>Сума</translation>
+ <source>Copy &amp;Address</source>
+ <translation>Скопіювати &amp;адресу</translation>
</message>
<message>
- <source>Label</source>
- <translation>Мітка</translation>
+ <source>&amp;Save Image...</source>
+ <translation>&amp;Зберегти зображення...</translation>
</message>
<message>
- <source>Message</source>
- <translation>Повідомлення</translation>
+ <source>Request payment to %1</source>
+ <translation>Запит платежу на %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>Гаманець</translation>
+ <source>Payment information</source>
+ <translation>Інформація про платіж</translation>
</message>
</context>
<context>
@@ -2373,8 +2542,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Ви впевнені, що хочете відправити?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>Перегляньте пропозицію щодо транзакцій. Це призведе до частково підписаної трансакції Bitcoin (PSBT), яку ви можете скопіювати та підписати, наприклад, офлайн-гаманецем %1 або гаманцем, сумісний з PSBT.</translation>
+ <source>Create Unsigned</source>
+ <translation>Створити без підпису</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>Зберегти дані транзакції</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>Частково підписана транзакція (Binary) (* .psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT збережено</translation>
</message>
<message>
<source>or</source>
@@ -2385,6 +2566,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Ви можете збільшити комісію пізніше (сигналізує Заміна-Через-Комісію, 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>
+ <translation>Перегляньте свою пропозицію щодо транзакції. Це призведе до частково Підписаної Транзакції Біткойна (PSBT), яку ви можете зберегти або скопіювати, а потім підписати, наприклад, офлайн-гаманцем %1 або апаратним гаманецем, сумісний з PSBT.</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>Будь-ласка, перевірте вашу транзакцію.</translation>
</message>
@@ -2413,18 +2598,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Підтвердити запропоновану комісію</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Скопіювати PSBT у буфер обміну</translation>
- </message>
- <message>
<source>Send</source>
<translation>Відправити</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>PSBT скопійовано</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Баланс тільки спостереження:</translation>
</message>
@@ -2501,11 +2678,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Choose previously used address</source>
- <translation>Обрати ранiш використовувану адресу</translation>
+ <translation>Обрати ранiше використану адресу</translation>
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation>Адреса Bitcoin для відправлення платежу</translation>
+ <translation>Адреса Біткойн для відправлення платежу</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2553,7 +2730,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>Введіть мітку для цієї адреси для додавання її в список використаних адрес</translation>
+ <translation>Введіть мітку цієї адреси для додавання її в перелік використаних адрес</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>
@@ -2599,7 +2776,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Choose previously used address</source>
- <translation>Обрати ранiш використовувану адресу</translation>
+ <translation>Обрати ранiше використану адресу</translation>
</message>
<message>
<source>Alt+A</source>
@@ -3130,7 +3307,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Comma separated file (*.csv)</source>
- <translation>Текст, разделённый запятыми (*.csv)</translation>
+ <translation>Файли (*.csv) розділені комами</translation>
</message>
<message>
<source>Confirmed</source>
@@ -3150,11 +3327,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Label</source>
- <translation>Метка</translation>
+ <translation>Мітка</translation>
</message>
<message>
<source>Address</source>
- <translation>Адрес</translation>
+ <translation>Адреса</translation>
</message>
<message>
<source>ID</source>
@@ -3162,7 +3339,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Exporting Failed</source>
- <translation>Экспорт не удался</translation>
+ <translation>Помилка експорту</translation>
</message>
<message>
<source>There was an error trying to save the transaction history to %1.</source>
@@ -3196,7 +3373,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<name>WalletController</name>
<message>
<source>Close wallet</source>
- <translation>закрити Гаманець</translation>
+ <translation>Закрити гаманець</translation>
</message>
<message>
<source>Are you sure you wish to close the wallet &lt;i&gt;%1&lt;/i&gt;?</source>
@@ -3206,12 +3383,26 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Якщо занадто довго закривати гаманець, це може призвести до необхідності повторної синхронізації всієї ланцюга, якщо ввімкнено обрізку.</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>Закрити всі гаманці</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>Ви впевнені, що хочете закрити всі гаманці?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>Жоден гаманець не завантажено.</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>Жоден гаманець не завантажений. Перейдіть у меню Файл&gt; Відкрити гаманець, щоб завантажити гаманець. - АБО -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>Створити новий гаманець</translation>
</message>
</context>
<context>
@@ -3270,18 +3461,42 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>default wallet</source>
- <translation>гаманець за змовчуванням</translation>
+ <translation>типовий гаманець</translation>
</message>
</context>
<context>
<name>WalletView</name>
<message>
<source>&amp;Export</source>
- <translation>&amp;Экспорт</translation>
+ <translation>&amp;Експортувати</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
- <translation>Экспортировать данные текущей вкладки в файл</translation>
+ <translation>Експортувати дані з поточної вкладки в файл</translation>
+ </message>
+ <message>
+ <source>Error</source>
+ <translation>Помилка</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>Не вдається декодувати PSBT з буфера обміну (недійсний base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>Завантажити дані транзакції</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>Частково підписана транзакція (* .psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>Файл PSBT повинен бути менше 100 Мб</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>Не вдається декодувати PSBT</translation>
</message>
<message>
<source>Backup Wallet</source>
@@ -3327,10 +3542,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Операція відсікання: остання синхронізація вмісту гаманцю не обмежується діями над скороченими данними. Вам необхідно зробити переіндексацію -reindex (заново завантажити веcь ланцюжок блоків в разі появи скороченого ланцюга)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Помилка: Сталася фатальна помилка (детальніший опис наведено в debug.log)</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Скорочення кількості блоків...</translation>
</message>
@@ -3343,10 +3554,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Розробники %s</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Неможливо створити ключ зміни адреси. У внутрішній пулі клавіш немає клавіш і жоден ключ не може генерувати.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Неможливо блокувати каталог даних %s. %s, ймовірно, вже працює.</translation>
</message>
@@ -3359,6 +3566,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Помилка читання %s! Всі ключі зчитано правильно, але записи в адресній книзі, або дані транзакцій можуть бути відсутніми чи невірними.</translation>
</message>
<message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation>Надано більше однієї адреси прив'язки служби Tor. Використання %s для автоматично створеної служби Tor.</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>Перевірте правильність дати та часу комп'ютера. Якщо ваш годинник налаштовано невірно, %s не буде працювати належним чином.</translation>
</message>
@@ -3367,6 +3578,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Будь ласка, зробіть внесок, якщо ви знаходите %s корисним. Відвідайте %s для отримання додаткової інформації про програмне забезпечення.</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase: Не вдалося підготувати оператор для отримання версії схеми гаманця: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Не вдалося підготувати оператор для отримання ідентифікатора програми: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation>SQLiteDatabase: Невідома версія схеми гаманця %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>Схоже, що база даних блоків містить блок з майбутнього. Це може статися із-за некоректно встановленої дати та/або часу. Перебудовуйте базу даних блоків лише тоді, коли ви переконані, що встановлено правильну дату і час</translation>
</message>
@@ -3395,14 +3618,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Попередження: неможливо досягти консенсусу з підключеними вузлами! Вам, або іншим вузлам необхідно оновити програмне забезпечення.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d з останніх 100 блоків мають неочікувану версію</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s пошкоджено, відновлення невдале</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool має бути не менше %d МБ</translation>
</message>
@@ -3479,6 +3694,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Помилка пересканування гаманця під час ініціалізації</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>Не вдалося перевірити базу даних</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>Імпорт...</translation>
</message>
@@ -3507,6 +3726,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Невірна сума для зарезервованої комісії -fallbackfee=&lt;amount&gt;: '%s'</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Не вдалося виконати оператор для перевірки бази даних: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>QLiteDatabase: Не вдалося отримати версію схеми гаманця: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch the application id: %s</source>
+ <translation>SQLiteDatabase: Не вдалося отримати ідентифікатор програми: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase: Не вдалося підготувати оператор для перевірки бази даних: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase: Не вдалося прочитати помилку перевірки бази даних: %s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase: Несподіваний ідентифікатор програми. Очікується %u, отримано %u</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>Зазначений каталог блоків "%s" не існує.</translation>
</message>
@@ -3527,10 +3770,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Завантаження P2P адрес...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Помилка: замало дискового простору!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Завантаження бан-списку...</translation>
</message>
@@ -3595,6 +3834,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Помилка: Не вдалося налаштувати прослуховування вхідних підключень (listen повернув помилку: %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s пошкоджено. Спробуйте скористатися інструментом гаманця bitcoin-wallet для відновлення або відновлення резервної копії.</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>Неможливо оновити спліт-гаманець, що не є HD, без оновлення, щоб підтримати попередньо розділений пул ключів. Будь ласка, використовуйте версію 169900 або не вказану версію.</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>Неприпустима сума для -maxtxfee = &lt;amount&gt;: «%s» ( плата повинна бути, принаймні %s, щоб запобігти зависанню транзакцій)</translation>
</message>
@@ -3603,10 +3850,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Залишок від суми транзакції зі сплатою комісії занадто малий</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>Ця помилка може статися, якщо цей гаманець не було чисто вимкнено і востаннє завантажений за допомогою збірки з новою версією Berkeley DB. Якщо так, будь ласка, використовуйте програмне забезпечення, яке востаннє завантажувало цей гаманець</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>Це максимальна комісія за транзакцію, яку ви сплачуєте (на додаток до звичайної комісії), щоб надавати пріоритет частковому уникненню витрат перед регулярним вибором монет.</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>Транзакція потребує наявності адреси для отримання решти, але ми не змогли її згенерувати. Будь ласка, спочатку виконайте регенерацію пулу ключів.</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>Вам необхідно перебудувати базу даних з використанням -reindex для завантаження повного ланцюжка блоків.</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>Виникла фатальна внутрішня помилка, див. debug.log для деталей</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>Неможливо встановити -peerblockfilters без -blockfilterindex.</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>Місця на диску занадто мало!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>Помилка читання бази даних, припиняю роботу.</translation>
</message>
@@ -3619,6 +3890,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Помилка: для %s бракує місця на диску</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>Помилка: Пул ключів закінчився, потрібно викликати keypoolrefill вдруге</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>Ставка комісії (%s) нижча за встановлену мінімальну ставку комісії (%s)</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>Невірна -onion адреса або ім'я хоста: '%s'</translation>
</message>
@@ -3639,6 +3918,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Необхідно вказати порт для -whitebind: «%s»</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>Не вказано проксі-сервер. Використовуйте -проксі=&lt;ip&gt; або -проксі=&lt;ip:port&gt;.</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>Використання скороченого ланцюжка блоків несумісне з параметром -blockfilterindex.</translation>
</message>
@@ -3712,10 +3995,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Попередження: активовано невідомі нові правила (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Видалення всіх транзакцій з гаманця...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>Встановлено дуже велике значення -maxtxfee! Такі великі комісії можуть бути сплачені окремою транзакцією.</translation>
</message>
@@ -3728,10 +4007,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Загальна довжина рядку мережевої версії (%i) перевищує максимально допустиму (%i). Зменшіть число чи розмір коментарів клієнта користувача.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Попередження: файл гаманця пошкоджено, дані врятовано! Оригінальний %s збережено як %s в %s; якщо ваш баланс або транзакції некорректно відображаються, ви повинні відновити його з резервної копії.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s встановлено дуже високо!</translation>
</message>
@@ -3745,7 +4020,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>The wallet will avoid paying less than the minimum relay fee.</source>
- <translation>Кошелёк будет избегать оплат меньших, нежели минимальная комиссия передачи.</translation>
+ <translation>Гаманець не переведе кошти, якщо комісія становить менше мінімальної плати за транзакцію.</translation>
</message>
<message>
<source>This is the minimum transaction fee you pay on every transaction.</source>
@@ -3757,7 +4032,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Transaction amounts must not be negative</source>
- <translation>Сумма транзакции не должна быть отрицательной</translation>
+ <translation>Сума транзакції не повинна бути від'ємною</translation>
</message>
<message>
<source>Transaction has too long of a mempool chain</source>
@@ -3776,10 +4051,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>Недостатньо коштів</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Неможливо оновити не-HD гаманець без оновлення підтримки пулу ключів. Будь-ласка використовуйте -upgradewallet=169900 чи -upgradewallet без вказівки версії. </translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>Оцінка комісії не вдалася. Fallbackfee вимкнено. Зачекайте кілька блоків або ввімкніть -fallbackfee.</translation>
</message>
@@ -3789,7 +4060,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Cannot write to data directory '%s'; check permissions.</source>
- <translation>Неможливо записати до каталог даних '%s'; перевірте дозвіл.</translation>
+ <translation>Неможливо записати до каталогу даних '%s'; перевірте дозвіл.</translation>
</message>
<message>
<source>Loading block index...</source>
diff --git a/src/qt/locale/bitcoin_ur.ts b/src/qt/locale/bitcoin_ur.ts
index d16c65ede4..647e32749f 100644
--- a/src/qt/locale/bitcoin_ur.ts
+++ b/src/qt/locale/bitcoin_ur.ts
@@ -62,6 +62,10 @@
<translation>پتے موصول ہورہے ہیں</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>یہ آپ کے ادائیگی بھیجنے کے لئے بٹ کوائن ایڈریس ہیں.سکے بھیجنے سے پہلے ہمیشہ رقم اور وصول کنندہ پتہ چیک کریں۔</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>&amp;پتا نقل کریں</translation>
</message>
@@ -100,10 +104,18 @@
<source>Address</source>
<translation>پتہ</translation>
</message>
- </context>
+ <message>
+ <source>(no label)</source>
+ <translation>(کوئی لیبل نہیں)</translation>
+ </message>
+</context>
<context>
<name>AskPassphraseDialog</name>
<message>
+ <source>Passphrase Dialog</source>
+ <translation>پاسفریج ڈائیلاگ</translation>
+ </message>
+ <message>
<source>Enter passphrase</source>
<translation>پاس فریز داخل کریں</translation>
</message>
@@ -115,6 +127,26 @@
<source>Repeat new passphrase</source>
<translation>نیا پاس فریز دہرائیں</translation>
</message>
+ <message>
+ <source>Show passphrase</source>
+ <translation>پاسفریز دکھائیں</translation>
+ </message>
+ <message>
+ <source>Encrypt wallet</source>
+ <translation>بٹوے کو خفیہ کریں</translation>
+ </message>
+ <message>
+ <source>Decrypt wallet</source>
+ <translation>ڈکرپٹ والیٹ</translation>
+ </message>
+ <message>
+ <source>Change passphrase</source>
+ <translation>پاسفریز تبدیل کریں</translation>
+ </message>
+ <message>
+ <source>Confirm wallet encryption</source>
+ <translation>پرس کی خفیہ کاری کی تصدیق کریں</translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -140,6 +172,10 @@
<source>Date</source>
<translation>تاریخ</translation>
</message>
+ <message>
+ <source>(no label)</source>
+ <translation>(کوئی لیبل نہیں)</translation>
+ </message>
</context>
<context>
<name>CreateWalletActivity</name>
@@ -191,6 +227,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -215,20 +254,12 @@
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;Address</source>
- <translation>کاپی پتہ</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>پتہ</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>رقم</translation>
+ <source>Amount:</source>
+ <translation>رقم:</translation>
</message>
<message>
- <source>Label</source>
- <translation>لیبل</translation>
+ <source>Copy &amp;Address</source>
+ <translation>کاپی پتہ</translation>
</message>
</context>
<context>
@@ -241,6 +272,10 @@
<source>Label</source>
<translation>لیبل</translation>
</message>
+ <message>
+ <source>(no label)</source>
+ <translation>(کوئی لیبل نہیں)</translation>
+ </message>
</context>
<context>
<name>SendCoinsDialog</name>
@@ -256,7 +291,11 @@
<source>Balance:</source>
<translation>بیلنس:</translation>
</message>
- </context>
+ <message>
+ <source>(no label)</source>
+ <translation>(کوئی لیبل نہیں)</translation>
+ </message>
+</context>
<context>
<name>SendCoinsEntry</name>
</context>
@@ -293,6 +332,10 @@
<source>Label</source>
<translation>لیبل</translation>
</message>
+ <message>
+ <source>(no label)</source>
+ <translation>(کوئی لیبل نہیں)</translation>
+ </message>
</context>
<context>
<name>TransactionView</name>
@@ -343,6 +386,10 @@
<source>Export the data in the current tab to a file</source>
<translation>موجودہ ڈیٹا کو فائیل میں محفوظ کریں</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>نقص</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_uz@Cyrl.ts b/src/qt/locale/bitcoin_uz@Cyrl.ts
index 4afabdb325..e5dd58d3c8 100644
--- a/src/qt/locale/bitcoin_uz@Cyrl.ts
+++ b/src/qt/locale/bitcoin_uz@Cyrl.ts
@@ -413,11 +413,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Ҳамён &lt;b&gt;кодланган&lt;/b&gt; ва вақтинча &lt;b&gt;қулфланган&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Жиддий хато юз берди. Bitcoin хавфсиз ишлай олмайди, шунинг учун чиқиб кетилади.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -865,7 +861,14 @@
<source>Current total balance in watch-only addresses</source>
<translation>Жорий умумий баланс фақат кўринадиган манзилларда</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>or</source>
+ <translation>ёки</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1021,10 +1024,6 @@
<translation>Хизматлар</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Тезликни бан қилиш</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Уланиш вақти</translation>
</message>
@@ -1093,14 +1092,6 @@
<translation>Ташқи йўналиш</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Ҳа</translation>
- </message>
- <message>
- <source>No</source>
- <translation>Йўқ</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Номаълум</translation>
</message>
@@ -1171,12 +1162,20 @@
<source>Copy amount</source>
<translation>Кийматни нусхала</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Ҳамён қулфдан чиқмади.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Коди</translation>
+ <source>Amount:</source>
+ <translation>Миқдори:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Хабар</translation>
</message>
<message>
<source>Copy &amp;Address</source>
@@ -1194,30 +1193,6 @@
<source>Payment information</source>
<translation>Тўлов маълумоти</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Манзил</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Миқдори</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Ёрлиқ</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Хабар</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Ҳамён</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -1793,11 +1768,7 @@
</context>
<context>
<name>WalletFrame</name>
- <message>
- <source>No wallet has been loaded.</source>
- <translation>Хали бирорта хамён юкланмади</translation>
- </message>
-</context>
+ </context>
<context>
<name>WalletModel</name>
<message>
@@ -1815,6 +1786,10 @@
<source>Export the data in the current tab to a file</source>
<translation>Жорий ички ойна ичидаги маълумотларни файлга экспорт қилиш</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>Хатолик</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_uz@Latn.ts b/src/qt/locale/bitcoin_uz@Latn.ts
index fcdde25df6..93455f2fb3 100644
--- a/src/qt/locale/bitcoin_uz@Latn.ts
+++ b/src/qt/locale/bitcoin_uz@Latn.ts
@@ -83,6 +83,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -102,14 +105,6 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>Manzil</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Yorliq</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_vi.ts b/src/qt/locale/bitcoin_vi.ts
index 33a4da9561..192442d6b9 100644
--- a/src/qt/locale/bitcoin_vi.ts
+++ b/src/qt/locale/bitcoin_vi.ts
@@ -70,10 +70,6 @@
<translation>Đâ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.</source>
- <translation>Những địa chỉ Bitcoin này để bạn nhận thanh toán. Sử dụng 'Tạo địa chỉ nhận mới'</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;Copy Địa Chỉ</translation>
</message>
@@ -629,11 +625,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>Ví thì &lt;b&gt;encrypted&lt;/b&gt; và hiện tại &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>Một lỗi nghiêm trọng vừa xảy ra. Bitcoin có thể không còn tiếp tục an toàn và sẽ bị bỏ.</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1135,10 +1127,6 @@
<translation>Hiển thị nếu cung cấp default SOCKS5 proxy is used to reach peers via this network type.</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>Dùng riêng lẻ proxy SOCKS&amp;5 để nối tới nốt mạng khác qua dịch vị ẩn Tor:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>Ẩn biểu tượng ở khay hệ thống</translation>
</message>
@@ -1271,10 +1259,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>Kết nối đến Bitcoin network qua một nhánh rời SOCKS5 proxy của Tor hidden services.</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>&amp;Window</translation>
</message>
@@ -1449,7 +1433,18 @@
<source>Current total balance in watch-only addresses</source>
<translation>Tổng số dư hiện tại trong watch-only addresses</translation>
</message>
-</context>
+ </context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Total Amount</source>
+ <translation>Tổng số</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>hoặc</translation>
+ </message>
+ </context>
<context>
<name>PaymentServer</name>
<message>
@@ -1713,10 +1708,6 @@
<translation>Block chain</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>Số blocks hiện tại</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>Pool Bộ Nhớ</translation>
</message>
@@ -1761,10 +1752,6 @@
<translation>Chọn một peer để xem thông tin chi tiết.</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>Whitelisted</translation>
- </message>
- <message>
<source>Direction</source>
<translation>Direction</translation>
</message>
@@ -1817,10 +1804,6 @@
<translation>Dịch vụ</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>Cấm Score</translation>
- </message>
- <message>
<source>Connection Time</source>
<translation>Connection Thời Gian</translation>
</message>
@@ -1969,14 +1952,6 @@
<translation>Outbound</translation>
</message>
<message>
- <source>Yes</source>
- <translation>Yes</translation>
- </message>
- <message>
- <source>No</source>
- <translation>No</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>Không biết</translation>
</message>
@@ -2075,12 +2050,24 @@
<source>Copy amount</source>
<translation>Sao chép số lượng</translation>
</message>
-</context>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>Không thể unlock wallet.</translation>
+ </message>
+ </context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Code</translation>
+ <source>Amount:</source>
+ <translation>Số lượng:</translation>
+ </message>
+ <message>
+ <source>Message:</source>
+ <translation>Tin nhắn:</translation>
+ </message>
+ <message>
+ <source>Wallet:</source>
+ <translation>Ví tiền</translation>
</message>
<message>
<source>Copy &amp;URI</source>
@@ -2102,30 +2089,6 @@
<source>Payment information</source>
<translation>Payment thông tin</translation>
</message>
- <message>
- <source>URI</source>
- <translation>URI</translation>
- </message>
- <message>
- <source>Address</source>
- <translation>Địa chỉ</translation>
- </message>
- <message>
- <source>Amount</source>
- <translation>Số lượng</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Nhãn</translation>
- </message>
- <message>
- <source>Message</source>
- <translation>Tin nhắn</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>Ví</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
@@ -2409,18 +2372,10 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Xác nhận đề xuất giao dịch</translation>
</message>
<message>
- <source>Copy PSBT to clipboard</source>
- <translation>Sao chép PSBT vào khay nhớ tạp clipboard</translation>
- </message>
- <message>
<source>Send</source>
<translation>Gửi</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>Đã sao chép PSBT</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>Số dư chỉ xem:</translation>
</message>
@@ -3202,12 +3157,12 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>Đó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>
</message>
-</context>
+ </context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>No wallet has been loaded.</translation>
+ <source>Create a new wallet</source>
+ <translation>Tạo một ví mới</translation>
</message>
</context>
<context>
@@ -3280,6 +3235,10 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Xuất dữ liệu trong thẻ hiện tại ra file</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>Lỗi</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
@@ -3323,10 +3282,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>Error: A fatal internal error occurred, see debug.log for details</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>Pruning blockstore...</translation>
</message>
@@ -3339,10 +3294,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>The %s developers</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>Không thể tạo khóa địa chỉ thay đổi. Không có các khóa trong hồ khóa keypool nội bộ và không thể tạo bất kì khóa nào.</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>Cannot obtain a lock on data directory %s. %s is probably already running.</translation>
</message>
@@ -3391,14 +3342,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>%d of last 100 blocks have unexpected version</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s corrupt, salvage failed</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool must be at least %d MB</translation>
</message>
@@ -3523,10 +3466,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Loading P2P addresses...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>Lỗi: Chổ tróng đĩa lưu trữ còn quá ít!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>Loading banlist...</translation>
</message>
@@ -3709,10 +3648,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Warning: unknown new rules activated (versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>Zapping all transactions from wallet...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</translation>
</message>
@@ -3725,10 +3660,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s is set very high!</translation>
</message>
@@ -3773,10 +3704,6 @@ Lưu ý: Vì phí được tính trên cơ sở mỗi byte, nên phí "100 satos
<translation>Không đủ tiền</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>Không thể nâng cấp một địa chỉ HD tách rời mà không nâng cấp hỗ trợ keypool tách rời trước. Làm ơn dùng upgradewallet=169900 hoặc -upgradewallet với không có chỉ ra phiên bản.</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>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>
diff --git a/src/qt/locale/bitcoin_yo.ts b/src/qt/locale/bitcoin_yo.ts
index 7094d2b3b4..f3f95ecb5f 100644
--- a/src/qt/locale/bitcoin_yo.ts
+++ b/src/qt/locale/bitcoin_yo.ts
@@ -87,6 +87,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
diff --git a/src/qt/locale/bitcoin_zh-Hans.ts b/src/qt/locale/bitcoin_zh-Hans.ts
index 5e2595eea3..93335756f2 100644
--- a/src/qt/locale/bitcoin_zh-Hans.ts
+++ b/src/qt/locale/bitcoin_zh-Hans.ts
@@ -30,6 +30,10 @@
<translation>从列表删除选定的地址</translation>
</message>
<message>
+ <source>Enter address or label to search</source>
+ <translation>输入地址或者标签进行搜索</translation>
+ </message>
+ <message>
<source>Export the data in the current tab to a file</source>
<translation>导出当前数据到文件</translation>
</message>
@@ -66,6 +70,12 @@
<translation>这是你的比特币发币地址。发送前请确认发送数量和接收地址</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>这是你的比特币接收地址。点击接收选项卡中“创建新的接收地址”按钮来创建新的地址。
+签名只能使用“传统”类型的地址。</translation>
+ </message>
+ <message>
<source>&amp;Copy Address</source>
<translation>复制地址</translation>
</message>
@@ -112,9 +122,41 @@
<context>
<name>AskPassphraseDialog</name>
<message>
+ <source>Passphrase Dialog</source>
+ <translation>密码对话框</translation>
+ </message>
+ <message>
+ <source>Enter passphrase</source>
+ <translation>输入密码</translation>
+ </message>
+ <message>
+ <source>New passphrase</source>
+ <translation>新密码</translation>
+ </message>
+ <message>
+ <source>Repeat new passphrase</source>
+ <translation>重复输入新密码</translation>
+ </message>
+ <message>
+ <source>Show passphrase</source>
+ <translation>显示密码</translation>
+ </message>
+ <message>
<source>Encrypt wallet</source>
<translation>加密钱包</translation>
</message>
+ <message>
+ <source>This operation needs your wallet passphrase to unlock the wallet.</source>
+ <translation>此操作需要您的钱包密码用来解锁钱包。</translation>
+ </message>
+ <message>
+ <source>Unlock wallet</source>
+ <translation>解锁钱包</translation>
+ </message>
+ <message>
+ <source>This operation needs your wallet passphrase to decrypt the wallet.</source>
+ <translation>此操作需要您的钱包密码用来解密钱包。</translation>
+ </message>
</context>
<context>
<name>BanTableModel</name>
@@ -163,6 +205,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -182,14 +227,6 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>地址</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>标签</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/locale/bitcoin_zh.ts b/src/qt/locale/bitcoin_zh.ts
index 52b2f24927..f67c74ec21 100644
--- a/src/qt/locale/bitcoin_zh.ts
+++ b/src/qt/locale/bitcoin_zh.ts
@@ -70,10 +70,6 @@
<translation>这些是你的比特币支付地址。在发送之前,一定要核对金额和接收地址。</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.</source>
- <translation>这些是您的比特币接收地址。建议每个交易使用一个新的接收地址。</translation>
- </message>
- <message>
<source>&amp;Copy Address</source>
<translation>&amp;复制地址</translation>
</message>
@@ -617,11 +613,7 @@
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</source>
<translation>钱包是&lt;b&gt;加密的&lt;/b&gt;,目前&lt;b&gt;已锁定&lt;/b&gt;</translation>
</message>
- <message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>发生了致命错误。比特币无法继续安全运行,将退出。</translation>
- </message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -1047,6 +1039,9 @@
</message>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -1115,20 +1110,20 @@
<source>Copy amount</source>
<translation>复制金额</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
<message>
- <source>Address</source>
- <translation>地址</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>不能解锁钱包</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Amount</source>
- <translation>总计</translation>
+ <source>Amount:</source>
+ <translation>总计:</translation>
</message>
<message>
- <source>Label</source>
- <translation>标签</translation>
+ <source>Wallet:</source>
+ <translation>钱包:</translation>
</message>
</context>
<context>
@@ -1436,7 +1431,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</context>
<context>
<name>WalletFrame</name>
- </context>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>创建一个新的钱包</translation>
+ </message>
+</context>
<context>
<name>WalletModel</name>
<message>
@@ -1454,6 +1453,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Export the data in the current tab to a file</source>
<translation>将当前选项卡中的数据导出到文件</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>错误</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_zh_CN.ts b/src/qt/locale/bitcoin_zh_CN.ts
index 8540c05b8d..fedc4a9c80 100644
--- a/src/qt/locale/bitcoin_zh_CN.ts
+++ b/src/qt/locale/bitcoin_zh_CN.ts
@@ -70,8 +70,10 @@
<translation>您可以给这些比特币地址付款。在付款之前,务必要检查金额和收款地址是否正确。</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.</source>
- <translation>您可以用这些比特币地址收款。使用“接收”标签页中的"创建新收款地址"按钮创建新地址。</translation>
+ <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>这是您用来收款的比特币地址。使用“接收”标签页中的“创建新收款地址”按钮来创建新的收款地址。
+只有“传统(legacy)”类型的地址支持签名。</translation>
</message>
<message>
<source>&amp;Copy Address</source>
@@ -482,6 +484,22 @@
<translation>已是最新</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>从文件加载PSBT...(&amp;L)</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>加载部分签名比特币交易(PSBT)</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>从剪贴板加载PSBT...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>从剪贴板中加载部分签名比特币交易(PSBT)</translation>
+ </message>
+ <message>
<source>Node window</source>
<translation>节点窗口</translation>
</message>
@@ -518,10 +536,26 @@
<translation>关闭钱包</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>关闭所有钱包...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>关闭所有钱包</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>显示 %1 帮助信息,获取可用命令行选项列表</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>不明文显示数值(&amp;M)</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>在“概况”标签页中不明文显示数值、只显示掩码</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>默认钱包</translation>
</message>
@@ -630,8 +664,12 @@
<translation>钱包已被&lt;b&gt;加密&lt;/b&gt;,当前为&lt;b&gt;锁定&lt;/b&gt;状态</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>发生严重错误。客户端无法安全地继续运行,即将退出。</translation>
+ <source>Original message:</source>
+ <translation>原消息:</translation>
+ </message>
+ <message>
+ <source>A fatal error occurred. %1 can no longer continue safely and will quit.</source>
+ <translation>发生致命错误。%1 已经无法继续安全运行并即将退出。</translation>
</message>
</context>
<context>
@@ -835,6 +873,14 @@
<translation>创建空白钱包</translation>
</message>
<message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>使用输出描述符进行scriptPubKey管理</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>输出描述符钱包</translation>
+ </message>
+ <message>
<source>Create</source>
<translation>创建</translation>
</message>
@@ -1139,10 +1185,6 @@
<translation>显示默认的SOCKS5代理是否被用于在该类型的网络下连接同伴。</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>连接Tor隐藏服务节点时使用另一个SOCKS&amp;5代理:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>不在系统通知区域显示图标。</translation>
</message>
@@ -1275,10 +1317,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>通过 Tor 隐藏服务连接比特币网络时使用另一个 SOCKS5 代理。</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>窗口(&amp;W)</translation>
</message>
@@ -1319,6 +1357,14 @@
<translation>是否显示手动选币功能。</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>连接比特币网络时专门为Tor onion服务使用另一个 SOCKS5 代理。</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>连接Tor onion服务节点时使用另一个SOCKS&amp;5代理:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>第三方交易网址(&amp;T)</translation>
</message>
@@ -1453,6 +1499,133 @@
<source>Current total balance in watch-only addresses</source>
<translation>仅观察地址中的当前总余额</translation>
</message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>“概况”标签页已启用隐私模式。要明文显示数值,请在设置中取消勾选“不明文显示数值”。</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>会话</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>签名交易</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>广播交易</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>复制到剪贴板</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>保存...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>关闭</translation>
+ </message>
+ <message>
+ <source>Failed to load transaction: %1</source>
+ <translation>加载交易失败: %1</translation>
+ </message>
+ <message>
+ <source>Failed to sign transaction: %1</source>
+ <translation>签名交易失败: %1</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>没有交易输入项可供签名了。</translation>
+ </message>
+ <message>
+ <source>Signed %1 inputs, but more signatures are still required.</source>
+ <translation>已签名 %1 个交易输入项,但是仍然还有余下的项目需要签名。</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>成功签名交易。交易已经可以广播。</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>处理交易时遇到未知错误。</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast successfully! Transaction ID: %1</source>
+ <translation>已成功广播交易!交易ID: %1</translation>
+ </message>
+ <message>
+ <source>Transaction broadcast failed: %1</source>
+ <translation>交易广播失败: %1</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>已复制PSBT到剪贴板</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>保存交易数据</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>部分签名交易(二进制) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT已保存到硬盘</translation>
+ </message>
+ <message>
+ <source> * Sends %1 to %2</source>
+ <translation> * 发送 %1 至 %2</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>无法计算交易费用或总交易金额。</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>支付交易费用:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>总额</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>或</translation>
+ </message>
+ <message>
+ <source>Transaction has %1 unsigned inputs.</source>
+ <translation>交易中含有%1个未签名输入项。</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>交易中有输入项缺失某些信息。</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>交易仍然需要签名。</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(但这个钱包不能签名交易)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(但这个钱包没有正确的密钥)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>交易已经完全签名,可以广播。</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>交易状态未知。</translation>
+ </message>
</context>
<context>
<name>PaymentServer</name>
@@ -1619,6 +1792,10 @@
<translation>错误: %1</translation>
</message>
<message>
+ <source>Error initializing settings: %1</source>
+ <translation>初始化设置出错: %1</translation>
+ </message>
+ <message>
<source>%1 didn't yet exit safely...</source>
<translation>%1 尚未安全退出...</translation>
</message>
@@ -1717,10 +1894,6 @@
<translation>区块链</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>当前区块数量</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>内存池</translation>
</message>
@@ -1765,10 +1938,6 @@
<translation>选择节点查看详细信息。</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>白名单</translation>
- </message>
- <message>
<source>Direction</source>
<translation>方向</translation>
</message>
@@ -1805,6 +1974,10 @@
<translation>节点窗口</translation>
</message>
<message>
+ <source>Current block height</source>
+ <translation>当前区块高度</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>打开当前数据目录中的 %1 调试日志文件。日志文件大的话可能要等上几秒钟。</translation>
</message>
@@ -1817,12 +1990,12 @@
<translation>放大字体大小</translation>
</message>
<message>
- <source>Services</source>
- <translation>服务</translation>
+ <source>Permissions</source>
+ <translation>权限</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>封禁记分</translation>
+ <source>Services</source>
+ <translation>服务</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1973,14 +2146,6 @@
<translation>传出</translation>
</message>
<message>
- <source>Yes</source>
- <translation>是</translation>
- </message>
- <message>
- <source>No</source>
- <translation>否</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>未知</translation>
</message>
@@ -2079,56 +2244,60 @@
<source>Copy amount</source>
<translation>复制金额</translation>
</message>
+ <message>
+ <source>Could not unlock wallet.</source>
+ <translation>无法解锁钱包。</translation>
+ </message>
+ <message>
+ <source>Could not generate new %1 address</source>
+ <translation>无法生成新的%1地址</translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>二维码</translation>
- </message>
- <message>
- <source>Copy &amp;URI</source>
- <translation>复制 &amp;URI</translation>
+ <source>Request payment to ...</source>
+ <translation>请求付款到 ...</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>复制地址(&amp;A)</translation>
+ <source>Address:</source>
+ <translation>地址:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>保存图像(&amp;S)...</translation>
+ <source>Amount:</source>
+ <translation>金额:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>请求付款到 %1</translation>
+ <source>Label:</source>
+ <translation>标签:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>付款信息</translation>
+ <source>Message:</source>
+ <translation>消息:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>钱包:</translation>
</message>
<message>
- <source>Address</source>
- <translation>地址</translation>
+ <source>Copy &amp;URI</source>
+ <translation>复制 &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>金额</translation>
+ <source>Copy &amp;Address</source>
+ <translation>复制地址(&amp;A)</translation>
</message>
<message>
- <source>Label</source>
- <translation>标签</translation>
+ <source>&amp;Save Image...</source>
+ <translation>保存图像(&amp;S)...</translation>
</message>
<message>
- <source>Message</source>
- <translation>消息</translation>
+ <source>Request payment to %1</source>
+ <translation>请求付款到 %1</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>钱包</translation>
+ <source>Payment information</source>
+ <translation>付款信息</translation>
</message>
</context>
<context>
@@ -2377,8 +2546,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>您确定要发出吗?</translation>
</message>
<message>
- <source>Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.</source>
- <translation>请务必要审核您的交易提案。这将会产生一笔“部分签名比特币交易”(PSBT),您可以复制它,然后可以通过各种方式对它进行签名,比如,可以通过离线%1钱包或是兼容PSBT的硬件钱包来完成签名。</translation>
+ <source>Create Unsigned</source>
+ <translation>创建未签名交易</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>保存交易数据</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>部分签名交易(二进制) (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>已保存PSBT</translation>
</message>
<message>
<source>or</source>
@@ -2389,6 +2570,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>你可以后来再追加手续费(打上支持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>
+ <translation>请务必仔细检查您的交易请求。这会产生一个部分签名比特币交易(PSBT),可以把保存下来或复制出去,然后就可以对它进行签名,比如用离线%1钱包,或是用兼容PSBT的硬件钱包。</translation>
+ </message>
+ <message>
<source>Please, review your transaction.</source>
<translation>请检查您的交易。</translation>
</message>
@@ -2414,21 +2599,13 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Confirm transaction proposal</source>
- <translation>确认交易提案</translation>
- </message>
- <message>
- <source>Copy PSBT to clipboard</source>
- <translation>复制PSBT到剪贴板</translation>
+ <translation>确认交易请求</translation>
</message>
<message>
<source>Send</source>
<translation>发送</translation>
</message>
<message>
- <source>PSBT copied</source>
- <translation>已复制PSBT</translation>
- </message>
- <message>
<source>Watch-only balance:</source>
<translation>仅观察余额:</translation>
</message>
@@ -3210,12 +3387,28 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>启用修剪时,如果一个钱包被卸载太久,就必须重新同步整条区块链才能再次加载它。</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>关闭所有钱包</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>您确定想要关闭所有钱包吗?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>没有载入钱包。</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>未加载钱包。
+请转到“文件”菜单 &gt; “打开钱包”来加载一个钱包。
+- 或者 -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>创建一个新的钱包</translation>
</message>
</context>
<context>
@@ -3288,6 +3481,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>将当前标签页数据导出到文件</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>错误</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>无法从剪贴板解码PSBT(Base64值无效)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>加载交易数据</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>部分签名交易 (*.psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PSBT文件必须小于100MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>无法解码PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>备份钱包</translation>
</message>
@@ -3331,10 +3548,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>修剪:上次同步钱包的位置已经超出(落后于)现有修剪后数据的范围。你需要进行-reindex(对于已经启用修剪节点,就需要重新下载整个区块链)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>错误:发生了致命的内部错误,详情见 debug.log 文件</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>正在修剪区块存储...</translation>
</message>
@@ -3347,10 +3560,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%s 开发者</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>无法生成找零地址密钥。 内部密钥池中没有密钥,也无法生成任何密钥。</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>无法锁定数据目录 %s。%s 可能已经在运行。</translation>
</message>
@@ -3363,6 +3572,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>读取 %s 时发生错误!所有的密钥都可以正确读取,但是交易记录或地址簿数据可能已经丢失或出错。</translation>
</message>
<message>
+ <source>More than one onion bind address is provided. Using %s for the automatically created Tor onion service.</source>
+ <translation>提供多个洋葱路由绑定地址。对自动创建的洋葱服务用%s</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>请检查电脑的日期时间设置是否正确!时间错误可能会导致 %s 运行异常。</translation>
</message>
@@ -3371,6 +3584,18 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>如果你认为%s对你比较有用的话,请对我们进行一些自愿贡献。请访问%s网站来获取有关这个软件的更多信息。</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase:无法获取sqlit钱包版本:%s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s</source>
+ <translation>SQLiteDatabase:无法获取应用ID:%s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported</source>
+ <translation>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>区块数据库包含未来的交易,这可能是由本机错误的日期时间引起。若确认本机日期时间正确,请重新建立区块数据库。</translation>
</message>
@@ -3399,14 +3624,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>警告:我们和其他节点似乎没达成共识!您可能需要升级,或者就是其他节点可能需要升级。</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>最后100个区块中的%d个包含未知的版本号</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>%s 已损坏,抢救失败</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>-maxmempool 最小为%d MB</translation>
</message>
@@ -3483,6 +3700,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>初始化时重扫描钱包失败</translation>
</message>
<message>
+ <source>Failed to verify database</source>
+ <translation>校验数据库失败</translation>
+ </message>
+ <message>
<source>Importing...</source>
<translation>导入中...</translation>
</message>
@@ -3511,6 +3732,26 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>参数 -fallbackfee=&lt;amount&gt;: '%s' 指定了无效的金额</translation>
</message>
<message>
+ <source>SQLiteDatabase: Failed to execute statement to verify database: %s</source>
+ <translation>SQLiteDatabase:校验数据库执行语句失败:%s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s</source>
+ <translation>SQLiteDatabase:无法获取sqlite钱包版本:%s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to prepare statement to verify database: %s</source>
+ <translation>SQLiteDatabase:无法准备语句来校验数据库:%s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Failed to read database verification error: %s</source>
+ <translation>SQLiteDatabase:无法读取数据库校验错误:%s</translation>
+ </message>
+ <message>
+ <source>SQLiteDatabase: Unexpected application id. Expected %u, got %u</source>
+ <translation>SQLiteDatabase:异常应用ID。异常%u,实际%u</translation>
+ </message>
+ <message>
<source>Specified blocks directory "%s" does not exist.</source>
<translation>指定的区块目录"%s"不存在。</translation>
</message>
@@ -3531,10 +3772,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>正在加载P2P地址...</translation>
</message>
<message>
- <source>Error: Disk space is too low!</source>
- <translation>错误:磁盘空间低!</translation>
- </message>
- <message>
<source>Loading banlist...</source>
<translation>正在加载黑名单...</translation>
</message>
@@ -3599,6 +3836,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>错误:监听外部连接失败 (listen函数返回了错误 %s)</translation>
</message>
<message>
+ <source>%s corrupt. Try using the wallet tool bitcoin-wallet to salvage or restoring a backup.</source>
+ <translation>%s损坏。请尝试用bitcoin-wallet钱包工具来对其进行急救。或者用一个备份进行还原。</translation>
+ </message>
+ <message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>无法在不支持“拆分前的密钥池”(pre split keypool)的情况下对“非拆分HD钱包”(non HD split wallet)进行升级。请使用版本号169900,或者压根不要指定版本号。</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>参数 -maxtxfee=&lt;amount&gt;: '%s' 指定了非法的金额 (手续费必须至少达到最小转发费率(minrelay fee) %s 以避免交易卡着发不出去)</translation>
</message>
@@ -3607,10 +3852,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>这笔交易在扣除手续费后的金额太小,以至于无法送出</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>如果这个钱包之前没有正确关闭,而且上一次是被新版的Berkeley DB加载过,就会发生这个错误。如果是这样,请使用上次加载过这个钱包的那个软件。</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>为了在常规选币过程中优先考虑避免“只花出一个地址上的一部分币”(partial spend)这种情况,您最多还需要(在常规手续费之外)付出的交易手续费。</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>交易需要一个找零地址,但是我们无法生成它。请先调用 keypoolrefill 。</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>您需要使用 -reindex 重新构建数据库以回到未修剪模式。这将重新下载整个区块链</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>发生了致命的内部错误,请在debug.log中查看详情</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>没有启用-blockfilterindex,就不能启用-peerblockfilters。</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>磁盘空间太低!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>读取数据库出错,关闭中。</translation>
</message>
@@ -3623,6 +3892,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>错误: %s 所在的磁盘空间低。</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>错误: 密钥池已被耗尽,请先调用keypoolrefill</translation>
+ </message>
+ <message>
+ <source>Fee rate (%s) is lower than the minimum fee rate setting (%s)</source>
+ <translation>手续费率 (%s) 低于最大手续费率设置 (%s)</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
<translation>无效的 -onion 地址: '%s'</translation>
</message>
@@ -3643,6 +3920,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>-whitebind: '%s' 需要指定一个端口</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>未指定代理服务器。请使用 -proxy=&lt;ip&gt; 或 -proxy=&lt;ip:port&gt; 。</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>修剪模式与 -blockfilterindex 不兼容。</translation>
</message>
@@ -3717,10 +3998,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>警告:不明的交易规则已经激活(versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>正在销毁钱包中的交易...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>参数 -maxtxfee 被设置得非常高!即使是单笔交易也可能付出如此之大的手续费。</translation>
</message>
@@ -3733,10 +4010,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>网络版本字符串的总长度 (%i) 超过最大长度 (%i) 了。请减少 uacomment 参数的数目或长度。</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>警告:钱包文件损坏,但数据被救回!原始的钱包文件%s已经重命名为%s并保存到%s目录下 。如果您的账户余额或者交易记录不正确,请使用您的钱包备份文件进行恢复。</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s非常高!</translation>
</message>
@@ -3781,10 +4054,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>金额不足</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>如果要对“非分离HD钱包(non HD split wallet)”进行升级,就必须先把它升级到支持“未进行分割的密钥池(pre split keypool)”的版本,否则无法进行升级。请使用指定了具体版本号的 -upgradewallet=169900 参数,或者直接使用不指定具体版本号的 -upgradewallet 参数重启钱包。</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>手续费估计失败。而且备用手续费估计(fallbackfee)已被禁用。请再等一些区块,或者通过-fallbackfee参数启用备用手续费估计。</translation>
</message>
diff --git a/src/qt/locale/bitcoin_zh_HK.ts b/src/qt/locale/bitcoin_zh_HK.ts
index 619cd0b768..56875462bc 100644
--- a/src/qt/locale/bitcoin_zh_HK.ts
+++ b/src/qt/locale/bitcoin_zh_HK.ts
@@ -417,6 +417,9 @@
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -536,19 +539,7 @@
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>地址</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>標記</translation>
- </message>
- <message>
- <source>Wallet</source>
- <translation>錢包</translation>
- </message>
-</context>
+ </context>
<context>
<name>RecentRequestsTableModel</name>
<message>
@@ -645,6 +636,10 @@
<source>Export the data in the current tab to a file</source>
<translation>把目前分頁的資料匯出至檔案</translation>
</message>
+ <message>
+ <source>Error</source>
+ <translation>錯誤</translation>
+ </message>
</context>
<context>
<name>bitcoin-core</name>
diff --git a/src/qt/locale/bitcoin_zh_TW.ts b/src/qt/locale/bitcoin_zh_TW.ts
index da1f92a461..2b71aed2f9 100644
--- a/src/qt/locale/bitcoin_zh_TW.ts
+++ b/src/qt/locale/bitcoin_zh_TW.ts
@@ -3,35 +3,35 @@
<name>AddressBookPage</name>
<message>
<source>Right-click to edit address or label</source>
- <translation>右鍵點一下來修改位址或標記</translation>
+ <translation>右鍵點擊來編輯地址或標籤</translation>
</message>
<message>
<source>Create a new address</source>
- <translation>產生一個新位址</translation>
+ <translation>產生一個新地址</translation>
</message>
<message>
<source>&amp;New</source>
- <translation>新增(&amp;N)</translation>
+ <translation>&amp;新增</translation>
</message>
<message>
<source>Copy the currently selected address to the system clipboard</source>
- <translation>複製目前選擇的位址到系統剪貼簿</translation>
+ <translation>複製目前選擇的地址到系統剪貼簿</translation>
</message>
<message>
<source>&amp;Copy</source>
- <translation>複製(&amp;C)</translation>
+ <translation>&amp;複製</translation>
</message>
<message>
<source>C&amp;lose</source>
- <translation>關閉(&amp;L)</translation>
+ <translation>C&amp;lose</translation>
</message>
<message>
<source>Delete the currently selected address from the list</source>
- <translation>把目前選擇的位址從列表中刪掉</translation>
+ <translation>把目前選擇的地址從清單中刪除</translation>
</message>
<message>
<source>Enter address or label to search</source>
- <translation>請輸入要搜尋的位址或標記</translation>
+ <translation>請輸入要搜尋的地址或標籤</translation>
</message>
<message>
<source>Export the data in the current tab to a file</source>
@@ -39,55 +39,56 @@
</message>
<message>
<source>&amp;Export</source>
- <translation>匯出(&amp;E)</translation>
+ <translation>&amp;匯出</translation>
</message>
<message>
<source>&amp;Delete</source>
- <translation>刪掉(&amp;D)</translation>
+ <translation>&amp;刪除</translation>
</message>
<message>
<source>Choose the address to send coins to</source>
- <translation>選擇要付錢過去的位址</translation>
+ <translation>選擇要發送幣過去的地址</translation>
</message>
<message>
<source>Choose the address to receive coins with</source>
- <translation>選擇要收錢進來的位址</translation>
+ <translation>選擇要接收幣的地址</translation>
</message>
<message>
<source>C&amp;hoose</source>
- <translation>選取(&amp;H)</translation>
+ <translation>C&amp;hoose</translation>
</message>
<message>
<source>Sending addresses</source>
- <translation>付款位址</translation>
+ <translation>發送地址</translation>
</message>
<message>
<source>Receiving addresses</source>
- <translation>收款位址</translation>
+ <translation>接收地址</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>這些是你要付款過去的 Bitcoin 位址。在付錢之前,務必要檢查金額和收款位址是否正確。</translation>
+ <translation>這些是你要發送過去的 比特幣地址。在發送幣之前,務必要檢查金額和接收地址是否正確。</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.</source>
- <translation>這些是您用於接收付款的比特幣位址。 使用接收分頁中的"生成新接收位址"按鈕創建新的位置。</translation>
+ <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>這些是您的比特幣接收地址。使用“接收”標籤中的“產生新的接收地址”按鈕產生新的地址。只能使用“傳統”類型的地址進行簽名。</translation>
</message>
<message>
<source>&amp;Copy Address</source>
- <translation>複製位址(&amp;C)</translation>
+ <translation>&amp;複製地址</translation>
</message>
<message>
<source>Copy &amp;Label</source>
- <translation>複製標記(&amp;L)</translation>
+ <translation>複製 &amp;標籤</translation>
</message>
<message>
<source>&amp;Edit</source>
- <translation>編輯(&amp;E)</translation>
+ <translation>&amp;編輯</translation>
</message>
<message>
<source>Export Address List</source>
- <translation>匯出位址清單</translation>
+ <translation>匯出地址清單</translation>
</message>
<message>
<source>Comma separated file (*.csv)</source>
@@ -99,7 +100,7 @@
</message>
<message>
<source>There was an error trying to save the address list to %1. Please try again.</source>
- <translation>儲存位址列表到 %1 時發生錯誤。請重試一次。</translation>
+ <translation>儲存地址清單到 %1 時發生錯誤。請重試一次。</translation>
</message>
</context>
<context>
@@ -110,7 +111,7 @@
</message>
<message>
<source>Address</source>
- <translation>位址</translation>
+ <translation>地址</translation>
</message>
<message>
<source>(no label)</source>
@@ -180,6 +181,14 @@
<translation>錢包已加密</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>輸入錢包的新密碼短語。&lt;br/&gt;請使用&lt;b&gt;個或10個以上隨機字符&lt;/b&gt;或&lt;b&gt;個8個以上單詞3的密碼。</translation>
+ </message>
+ <message>
+ <source>Enter the old passphrase and new passphrase for the wallet.</source>
+ <translation>輸入錢包的密碼短語和新密碼短語。</translation>
+ </message>
+ <message>
<source>Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.</source>
<translation>請記得, 即使將錢包加密, 也不能完全防止因惡意軟體入侵, 而導致位元幣被偷.</translation>
</message>
@@ -247,7 +256,7 @@
<name>BitcoinGUI</name>
<message>
<source>Sign &amp;message...</source>
- <translation>簽署訊息(&amp;M)...</translation>
+ <translation>簽名和訊息...</translation>
</message>
<message>
<source>Synchronizing with network...</source>
@@ -255,7 +264,7 @@
</message>
<message>
<source>&amp;Overview</source>
- <translation>總覽(&amp;O)</translation>
+ <translation>&amp;總覽</translation>
</message>
<message>
<source>Show general overview of wallet</source>
@@ -263,7 +272,7 @@
</message>
<message>
<source>&amp;Transactions</source>
- <translation>交易(&amp;T)</translation>
+ <translation>&amp;交易</translation>
</message>
<message>
<source>Browse transaction history</source>
@@ -271,17 +280,13 @@
</message>
<message>
<source>E&amp;xit</source>
- <translation>結束(&amp;X)</translation>
+ <translation>E&amp;xit</translation>
</message>
<message>
<source>Quit application</source>
<translation>結束應用程式</translation>
</message>
<message>
- <source>&amp;About %1</source>
- <translation>關於%1(&amp;A)</translation>
- </message>
- <message>
<source>Show information about %1</source>
<translation>顯示 %1 的相關資訊</translation>
</message>
@@ -295,7 +300,7 @@
</message>
<message>
<source>&amp;Options...</source>
- <translation>選項(&amp;O)...</translation>
+ <translation>&選項...</translation>
</message>
<message>
<source>Modify configuration options for %1</source>
@@ -303,27 +308,27 @@
</message>
<message>
<source>&amp;Encrypt Wallet...</source>
- <translation>加密錢包(&amp;E)...</translation>
+ <translation>&加密錢包...</translation>
</message>
<message>
<source>&amp;Backup Wallet...</source>
- <translation>備份錢包(&amp;B)...</translation>
+ <translation>&備份錢包...</translation>
</message>
<message>
<source>&amp;Change Passphrase...</source>
- <translation>改變密碼(&amp;C)...</translation>
+ <translation>&變更密碼短語...</translation>
</message>
<message>
<source>Open &amp;URI...</source>
- <translation>開啓 &amp;URI...</translation>
+ <translation>開啟 &amp;URI...</translation>
</message>
<message>
<source>Create Wallet...</source>
- <translation>新增錢包...</translation>
+ <translation>產生錢包...</translation>
</message>
<message>
<source>Create a new wallet</source>
- <translation>創建一個新錢包</translation>
+ <translation>產生一個新錢包</translation>
</message>
<message>
<source>Wallet:</source>
@@ -355,7 +360,7 @@
</message>
<message>
<source>Send coins to a Bitcoin address</source>
- <translation>付錢給一個 Bitcoin 位址</translation>
+ <translation>發送幣給一個比特幣地址</translation>
</message>
<message>
<source>Backup wallet to another location</source>
@@ -367,19 +372,19 @@
</message>
<message>
<source>&amp;Verify message...</source>
- <translation>驗證訊息(&amp;V)...</translation>
+ <translation>&amp;驗證訊息...</translation>
</message>
<message>
<source>&amp;Send</source>
- <translation>付款(&amp;S)</translation>
+ <translation>&amp;發送</translation>
</message>
<message>
<source>&amp;Receive</source>
- <translation>收款(&amp;R)</translation>
+ <translation>&amp;接收</translation>
</message>
<message>
<source>&amp;Show / Hide</source>
- <translation>顯示或隱藏(&amp;S)</translation>
+ <translation>&amp;顯示或隱藏</translation>
</message>
<message>
<source>Show or hide the main Window</source>
@@ -391,23 +396,23 @@
</message>
<message>
<source>Sign messages with your Bitcoin addresses to prove you own them</source>
- <translation>用 Bitcoin 位址簽署訊息來證明位址是你的</translation>
+ <translation>用比特幣地址簽名訊息來證明位址是你的</translation>
</message>
<message>
<source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
- <translation>驗證訊息是用來確定訊息是用指定的 Bitcoin 位址簽署的</translation>
+ <translation>驗證訊息是用來確定訊息是用指定的比特幣地址簽名的</translation>
</message>
<message>
<source>&amp;File</source>
- <translation>檔案(&amp;F)</translation>
+ <translation>&amp;檔案</translation>
</message>
<message>
<source>&amp;Settings</source>
- <translation>設定(&amp;S)</translation>
+ <translation>&amp;設定</translation>
</message>
<message>
<source>&amp;Help</source>
- <translation>說明(&amp;H)</translation>
+ <translation>&amp;說明</translation>
</message>
<message>
<source>Tabs toolbar</source>
@@ -419,15 +424,15 @@
</message>
<message>
<source>Show the list of used sending addresses and labels</source>
- <translation>顯示已使用過的付款位址和標記的清單</translation>
+ <translation>顯示已使用過的發送地址和標籤清單</translation>
</message>
<message>
<source>Show the list of used receiving addresses and labels</source>
- <translation>顯示已使用過的收款位址和標記的清單</translation>
+ <translation>顯示已使用過的接收地址和標籤清單</translation>
</message>
<message>
<source>&amp;Command-line options</source>
- <translation>命令列選項(&amp;C)</translation>
+ <translation>&amp;命令行選項</translation>
</message>
<message numerus="yes">
<source>%n active connection(s) to Bitcoin network</source>
@@ -474,12 +479,40 @@
<translation>最新狀態</translation>
</message>
<message>
+ <source>&amp;Load PSBT from file...</source>
+ <translation>從檔案中載入PSBT ...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction</source>
+ <translation>載入部分簽名的比特幣交易</translation>
+ </message>
+ <message>
+ <source>Load PSBT from clipboard...</source>
+ <translation>從剪貼簿載入PSBT ...</translation>
+ </message>
+ <message>
+ <source>Load Partially Signed Bitcoin Transaction from clipboard</source>
+ <translation>從剪貼簿載入部分簽名的比特幣交易</translation>
+ </message>
+ <message>
+ <source>Node window</source>
+ <translation>節點視窗</translation>
+ </message>
+ <message>
+ <source>Open node debugging and diagnostic console</source>
+ <translation>開啟節點調試和診斷控制台</translation>
+ </message>
+ <message>
<source>&amp;Sending addresses</source>
- <translation>付款位址(&amp;S)</translation>
+ <translation>&amp;發送地址</translation>
</message>
<message>
<source>&amp;Receiving addresses</source>
- <translation>收款位址(&amp;R)</translation>
+ <translation>&amp;接收地址</translation>
+ </message>
+ <message>
+ <source>Open a bitcoin: URI</source>
+ <translation>打開一個比特幣:URI</translation>
</message>
<message>
<source>Open Wallet</source>
@@ -498,10 +531,26 @@
<translation>關上錢包</translation>
</message>
<message>
+ <source>Close All Wallets...</source>
+ <translation>關閉所有錢包...</translation>
+ </message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>關閉所有錢包</translation>
+ </message>
+ <message>
<source>Show the %1 help message to get a list with possible Bitcoin command-line options</source>
<translation>顯示 %1 的說明訊息,來取得可用命令列選項的列表</translation>
</message>
<message>
+ <source>&amp;Mask values</source>
+ <translation>&遮罩值</translation>
+ </message>
+ <message>
+ <source>Mask the values in the Overview tab</source>
+ <translation>遮蔽“概述”選項卡中的值</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>預設錢包</translation>
</message>
@@ -511,11 +560,11 @@
</message>
<message>
<source>&amp;Window</source>
- <translation>視窗(&amp;W)</translation>
+ <translation>&amp;視窗</translation>
</message>
<message>
<source>Minimize</source>
- <translation>縮小</translation>
+ <translation>縮到最小</translation>
</message>
<message>
<source>Zoom</source>
@@ -527,11 +576,11 @@
</message>
<message>
<source>%1 client</source>
- <translation>%1 客戶端軟體</translation>
+ <translation>%1 客戶端</translation>
</message>
<message>
<source>Connecting to peers...</source>
- <translation>正在跟其他節點連線中...</translation>
+ <translation>正在跟其他peers連接中...</translation>
</message>
<message>
<source>Catching up...</source>
@@ -539,7 +588,7 @@
</message>
<message>
<source>Error: %1</source>
- <translation>错误:%1</translation>
+ <translation>錯誤:%1</translation>
</message>
<message>
<source>Warning: %1</source>
@@ -578,7 +627,7 @@
<message>
<source>Address: %1
</source>
- <translation>位址: %1
+ <translation>地址: %1
</translation>
</message>
<message>
@@ -599,7 +648,7 @@
</message>
<message>
<source>Private key &lt;b&gt;disabled&lt;/b&gt;</source>
- <translation>私钥&lt;b&gt;禁用&lt;/b&gt;</translation>
+ <translation>私鑰&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>
@@ -610,10 +659,10 @@
<translation>錢包&lt;b&gt;已加密&lt;/b&gt;並且&lt;b&gt;上鎖中&lt;/b&gt;</translation>
</message>
<message>
- <source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
- <translation>發生了致命的錯誤。Bitcoin 軟體沒辦法再繼續安全執行,只好結束。</translation>
+ <source>Original message:</source>
+ <translation>原始訊息:</translation>
</message>
-</context>
+ </context>
<context>
<name>CoinControlDialog</name>
<message>
@@ -650,7 +699,7 @@
</message>
<message>
<source>(un)select all</source>
- <translation>全選或全不選</translation>
+ <translation>(un)全選</translation>
</message>
<message>
<source>Tree mode</source>
@@ -670,7 +719,7 @@
</message>
<message>
<source>Received with address</source>
- <translation>收款位址</translation>
+ <translation>用地址接收</translation>
</message>
<message>
<source>Date</source>
@@ -686,7 +735,7 @@
</message>
<message>
<source>Copy address</source>
- <translation>複製位址</translation>
+ <translation>複製地址</translation>
</message>
<message>
<source>Copy label</source>
@@ -726,7 +775,7 @@
</message>
<message>
<source>Copy dust</source>
- <translation>複製零散金額</translation>
+ <translation>複製灰塵金額</translation>
</message>
<message>
<source>Copy change</source>
@@ -746,7 +795,7 @@
</message>
<message>
<source>This label turns red if any recipient receives an amount smaller than the current dust threshold.</source>
- <translation>當任何一個收款金額小於目前的零散金額上限時,文字會變紅色。</translation>
+ <translation>當任何一個收款金額小於目前的灰塵金額上限時,文字會變紅色。</translation>
</message>
<message>
<source>Can vary +/- %1 satoshi(s) per input.</source>
@@ -758,7 +807,7 @@
</message>
<message>
<source>change from %1 (%2)</source>
- <translation>找零前是 %1 (%2)</translation>
+ <translation>找零來自於 %1 (%2)</translation>
</message>
<message>
<source>(change)</source>
@@ -771,7 +820,11 @@
<source>Create wallet failed</source>
<translation>創建錢包失敗&lt;br&gt;</translation>
</message>
- </context>
+ <message>
+ <source>Create wallet warning</source>
+ <translation>產生錢包警告:</translation>
+ </message>
+</context>
<context>
<name>CreateWalletDialog</name>
<message>
@@ -782,12 +835,48 @@
<source>Wallet Name</source>
<translation>錢包名稱</translation>
</message>
- </context>
+ <message>
+ <source>Encrypt the wallet. The wallet will be encrypted with a passphrase of your choice.</source>
+ <translation>加密錢包。 錢包將使用您選擇的密碼進行加密。</translation>
+ </message>
+ <message>
+ <source>Encrypt Wallet</source>
+ <translation>加密錢包</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>禁用此錢包的私鑰。取消了私鑰的錢包將沒有私鑰,並且不能有HD種子或匯入的私鑰。這是只能看的錢包的理想選擇。</translation>
+ </message>
+ <message>
+ <source>Disable Private Keys</source>
+ <translation>禁用私鑰</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>製作一個空白的錢包。空白錢包最初沒有私鑰或腳本。以後可以匯入私鑰和地址,或者可以設定HD種子。</translation>
+ </message>
+ <message>
+ <source>Make Blank Wallet</source>
+ <translation>製作空白錢包</translation>
+ </message>
+ <message>
+ <source>Use descriptors for scriptPubKey management</source>
+ <translation>使用descriptors(描述符)進行scriptPubKey管理</translation>
+ </message>
+ <message>
+ <source>Descriptor Wallet</source>
+ <translation>描述符錢包</translation>
+ </message>
+ <message>
+ <source>Create</source>
+ <translation>產生</translation>
+ </message>
+</context>
<context>
<name>EditAddressDialog</name>
<message>
<source>Edit Address</source>
- <translation>編輯位址</translation>
+ <translation>編輯地址</translation>
</message>
<message>
<source>&amp;Label</source>
@@ -795,39 +884,35 @@
</message>
<message>
<source>The label associated with this address list entry</source>
- <translation>跟這個位址簿項目關聯的標記</translation>
+ <translation>與此地址清單關聯的標籤</translation>
</message>
<message>
<source>The address associated with this address list entry. This can only be modified for sending addresses.</source>
- <translation>跟這個位址簿項目關聯的位址。只有付款位址能被修改。</translation>
+ <translation>跟這個地址清單關聯的地址。只有發送地址能被修改。</translation>
</message>
<message>
<source>&amp;Address</source>
- <translation>位址(&amp;A)</translation>
+ <translation>&amp;地址</translation>
</message>
<message>
<source>New sending address</source>
- <translation>造新的付款位址</translation>
+ <translation>新的發送地址</translation>
</message>
<message>
<source>Edit receiving address</source>
- <translation>編輯收款位址</translation>
+ <translation>編輯接收地址</translation>
</message>
<message>
<source>Edit sending address</source>
- <translation>編輯付款位址</translation>
+ <translation>編輯發送地址</translation>
</message>
<message>
<source>The entered address "%1" is not a valid Bitcoin address.</source>
- <translation>輸入的位址 %1 並不是有效的 Bitcoin 位址。</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>%1 已經是標記為 %2 的收款位址了,不可以又是付款位址。</translation>
+ <translation>輸入的地址 %1 並不是有效的比特幣地址。</translation>
</message>
<message>
<source>The entered address "%1" is already in the address book with label "%2".</source>
- <translation>輸入的位址 %1 本來就在位址簿中了,標記為 %2。</translation>
+ <translation>輸入的地址 %1 已經在地址簿中了,標籤為 "%2"。</translation>
</message>
<message>
<source>Could not unlock wallet.</source>
@@ -895,6 +980,10 @@
<translation>在你按下「好」之後,%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>還原此設置需要重新下載整個區塊鏈。首先下載完整的鏈,然後再修剪它是更快的。禁用某些高級功能。</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>一開始的同步作業非常的耗費資源,並且可能會暴露出之前沒被發現的電腦硬體問題。每次執行 %1 的時候都會繼續先前未完成的下載。</translation>
</message>
@@ -946,7 +1035,11 @@
<source>(of %n GB needed)</source>
<translation><numerusform>(需要 %n GB)</numerusform></translation>
</message>
- </context>
+ <message numerus="yes">
+ <source>(%n GB needed for full chain)</source>
+ <translation><numerusform>(完整鏈需要%n GB)</numerusform></translation>
+ </message>
+</context>
<context>
<name>ModalOverlay</name>
<message>
@@ -1005,6 +1098,10 @@
<context>
<name>OpenURIDialog</name>
<message>
+ <source>Open bitcoin URI</source>
+ <translation>打開比特幣URI</translation>
+ </message>
+ <message>
<source>URI:</source>
<translation>URI:</translation>
</message>
@@ -1012,6 +1109,14 @@
<context>
<name>OpenWalletActivity</name>
<message>
+ <source>Open wallet failed</source>
+ <translation>打開錢包失敗</translation>
+ </message>
+ <message>
+ <source>Open wallet warning</source>
+ <translation>打開錢包警告</translation>
+ </message>
+ <message>
<source>default wallet</source>
<translation>默认钱包</translation>
</message>
@@ -1048,17 +1153,13 @@
</message>
<message>
<source>IP address of the proxy (e.g. IPv4: 127.0.0.1 / IPv6: ::1)</source>
- <translation>代理伺服器的網際網路位址(像是 IPv4 的 127.0.0.1 或 IPv6 的 ::1)</translation>
+ <translation>代理的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>如果對這種網路類型,有指定用來跟其他節點聯絡的 SOCKS5 代理伺服器的話,就會顯示在這裡。</translation>
</message>
<message>
- <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor hidden services:</source>
- <translation>透過另外的 SOCKS&amp;5 代理伺服器來連線到 Bitcoin 網路中的 Tor 隱藏服務:</translation>
- </message>
- <message>
<source>Hide the icon from the system tray.</source>
<translation>隱藏系統通知區圖示</translation>
</message>
@@ -1136,7 +1237,7 @@
</message>
<message>
<source>&amp;Spend unconfirmed change</source>
- <translation>可以花還沒確認的零錢(&amp;S)</translation>
+ <translation>&amp;可以花費還未確認的找零</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>
@@ -1191,10 +1292,6 @@
<translation>Tor</translation>
</message>
<message>
- <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor hidden services.</source>
- <translation>透過另外的 SOCKS5 代理伺服器來連線到 Bitcoin 網路中的 Tor 隱藏服務。</translation>
- </message>
- <message>
<source>&amp;Window</source>
<translation>視窗(&amp;W)</translation>
</message>
@@ -1235,6 +1332,14 @@
<translation>是否要顯示錢幣控制功能。</translation>
</message>
<message>
+ <source>Connect to the Bitcoin network through a separate SOCKS5 proxy for Tor onion services.</source>
+ <translation>通過用於Tor洋蔥服務個別的SOCKS5代理連接到比特幣網路。</translation>
+ </message>
+ <message>
+ <source>Use separate SOCKS&amp;5 proxy to reach peers via Tor onion services:</source>
+ <translation>使用個別的SOCKS&5代理介由Tor onion服務到達peers:</translation>
+ </message>
+ <message>
<source>&amp;Third party transaction URLs</source>
<translation>第三方交易網址連結(&amp;T)</translation>
</message>
@@ -1264,7 +1369,7 @@
</message>
<message>
<source>Client restart required to activate changes.</source>
- <translation>需要重新啟動客戶端軟體來讓改變生效。</translation>
+ <translation>需要重新開始客戶端軟體來讓改變生效。</translation>
</message>
<message>
<source>Client will be shut down. Do you want to proceed?</source>
@@ -1288,11 +1393,11 @@
</message>
<message>
<source>This change would require a client restart.</source>
- <translation>這項改變需要重新啟動客戶端軟體。</translation>
+ <translation>這個變更請求重新開始客戶端軟體。</translation>
</message>
<message>
<source>The supplied proxy address is invalid.</source>
- <translation>提供的代理伺服器位址無效。</translation>
+ <translation>提供的代理地址無效。</translation>
</message>
</context>
<context>
@@ -1347,7 +1452,7 @@
</message>
<message>
<source>Your current balance in watch-only addresses</source>
- <translation>所有只能看位址的目前餘額</translation>
+ <translation>所有只能看的地址的當前餘額</translation>
</message>
<message>
<source>Spendable:</source>
@@ -1359,15 +1464,114 @@
</message>
<message>
<source>Unconfirmed transactions to watch-only addresses</source>
- <translation>所有只能看位址還沒確認的交易</translation>
+ <translation>所有只能看的地址還未確認的交易</translation>
</message>
<message>
<source>Mined balance in watch-only addresses that has not yet matured</source>
- <translation>所有只能看位址還沒成熟的開採金額</translation>
+ <translation>所有只能看的地址還沒已熟成的挖出餘額</translation>
</message>
<message>
<source>Current total balance in watch-only addresses</source>
- <translation>所有只能看位址的目前全部餘額</translation>
+ <translation>所有只能看的地址的當前總餘額</translation>
+ </message>
+ <message>
+ <source>Privacy mode activated for the Overview tab. To unmask the values, uncheck Settings-&gt;Mask values.</source>
+ <translation>“總覽”選項卡啟用了隱私模式。要取消遮蔽值,請取消選取 設定-&gt;遮蔽值。</translation>
+ </message>
+</context>
+<context>
+ <name>PSBTOperationsDialog</name>
+ <message>
+ <source>Dialog</source>
+ <translation>對話視窗</translation>
+ </message>
+ <message>
+ <source>Sign Tx</source>
+ <translation>簽名交易</translation>
+ </message>
+ <message>
+ <source>Broadcast Tx</source>
+ <translation>廣播交易</translation>
+ </message>
+ <message>
+ <source>Copy to Clipboard</source>
+ <translation>複製到剪貼簿</translation>
+ </message>
+ <message>
+ <source>Save...</source>
+ <translation>儲存...</translation>
+ </message>
+ <message>
+ <source>Close</source>
+ <translation>關閉</translation>
+ </message>
+ <message>
+ <source>Could not sign any more inputs.</source>
+ <translation>無法再簽名 input</translation>
+ </message>
+ <message>
+ <source>Signed transaction successfully. Transaction is ready to broadcast.</source>
+ <translation>成功簽名交易。交易已準備好廣播。</translation>
+ </message>
+ <message>
+ <source>Unknown error processing transaction.</source>
+ <translation>處理交易有未知的錯誤</translation>
+ </message>
+ <message>
+ <source>PSBT copied to clipboard.</source>
+ <translation>PSBT已復製到剪貼簿</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>儲存交易資料</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>部分簽名的交易(二進制)(* .psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved to disk.</source>
+ <translation>PSBT已儲存到磁碟。</translation>
+ </message>
+ <message>
+ <source>Unable to calculate transaction fee or total transaction amount.</source>
+ <translation>無法計算交易手續費或總交易金額。</translation>
+ </message>
+ <message>
+ <source>Pays transaction fee: </source>
+ <translation>支付交易手續費:</translation>
+ </message>
+ <message>
+ <source>Total Amount</source>
+ <translation>總金額</translation>
+ </message>
+ <message>
+ <source>or</source>
+ <translation>或</translation>
+ </message>
+ <message>
+ <source>Transaction is missing some information about inputs.</source>
+ <translation>交易缺少有關 input 的一些訊息。</translation>
+ </message>
+ <message>
+ <source>Transaction still needs signature(s).</source>
+ <translation>交易仍需要簽名。</translation>
+ </message>
+ <message>
+ <source>(But this wallet cannot sign transactions.)</source>
+ <translation>(但是此錢包無法簽名交易。)</translation>
+ </message>
+ <message>
+ <source>(But this wallet does not have the right keys.)</source>
+ <translation>(但是這個錢包沒有正確的鑰匙)</translation>
+ </message>
+ <message>
+ <source>Transaction is fully signed and ready for broadcast.</source>
+ <translation>交易已完全簽名,可以廣播。</translation>
+ </message>
+ <message>
+ <source>Transaction status is unknown.</source>
+ <translation>交易狀態未知</translation>
</message>
</context>
<context>
@@ -1389,12 +1593,24 @@
<translation>字首為 bitcoin:// 不是有效的 URI,請改用 bitcoin: 開頭。</translation>
</message>
<message>
+ <source>Cannot process payment request because BIP70 is not supported.</source>
+ <translation>由於不支援BIP70,因此無法處理付款要求。</translation>
+ </message>
+ <message>
+ <source>Due to widespread security flaws in BIP70 it's strongly recommended that any merchant instructions to switch wallets be ignored.</source>
+ <translation>由於BIP70中存在廣泛的安全性漏洞,因此強烈建議您忽略任何商戶更換錢包的指示都將被忽略。</translation>
+ </message>
+ <message>
+ <source>If you are receiving this error you should request the merchant provide a BIP21 compatible URI.</source>
+ <translation>如果您收到此錯誤,則應請求商家提供與BIP21相容的URI。</translation>
+ </message>
+ <message>
<source>Invalid payment address %1</source>
- <translation>無效的付款位址 %1</translation>
+ <translation>無效支付地址 %1</translation>
</message>
<message>
<source>URI cannot be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>沒辦法解析 URI 位址!可能是因為 Bitcoin 位址無效,或是 URI 參數格式錯誤。</translation>
+ <translation>沒辦法解析 URI !可能是因為無效比特幣地址,或是 URI 參數格式錯誤。</translation>
</message>
<message>
<source>Payment request file handling</source>
@@ -1436,7 +1652,7 @@
</message>
<message>
<source>Enter a Bitcoin address (e.g. %1)</source>
- <translation>輸入 Bitcoin 位址 (比如說 %1)</translation>
+ <translation>輸入 比特幣地址 (比如說 %1)</translation>
</message>
<message>
<source>%1 d</source>
@@ -1621,10 +1837,6 @@
<translation>區塊鏈</translation>
</message>
<message>
- <source>Current number of blocks</source>
- <translation>目前區塊數</translation>
- </message>
- <message>
<source>Memory Pool</source>
<translation>記憶體暫存池</translation>
</message>
@@ -1669,10 +1881,6 @@
<translation>選一個節點來看詳細資訊</translation>
</message>
<message>
- <source>Whitelisted</source>
- <translation>列在白名單</translation>
- </message>
- <message>
<source>Direction</source>
<translation>方向</translation>
</message>
@@ -1693,10 +1901,26 @@
<translation>已同步區塊</translation>
</message>
<message>
+ <source>The mapped Autonomous System used for diversifying peer selection.</source>
+ <translation>映射的自治系統,用於使peer選取多樣化。</translation>
+ </message>
+ <message>
+ <source>Mapped AS</source>
+ <translation>對應 AS</translation>
+ </message>
+ <message>
<source>User Agent</source>
<translation>使用者代理</translation>
</message>
<message>
+ <source>Node window</source>
+ <translation>節點視窗</translation>
+ </message>
+ <message>
+ <source>Current block height</source>
+ <translation>當前區塊高度</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>從目前的資料目錄下開啓 %1 的除錯紀錄檔。當紀錄檔很大時,可能會花好幾秒的時間。</translation>
</message>
@@ -1709,12 +1933,12 @@
<translation>放大文字</translation>
</message>
<message>
- <source>Services</source>
- <translation>服務</translation>
+ <source>Permissions</source>
+ <translation>允許</translation>
</message>
<message>
- <source>Ban Score</source>
- <translation>惡劣分數</translation>
+ <source>Services</source>
+ <translation>服務</translation>
</message>
<message>
<source>Connection Time</source>
@@ -1865,14 +2089,6 @@
<translation>出去</translation>
</message>
<message>
- <source>Yes</source>
- <translation>是</translation>
- </message>
- <message>
- <source>No</source>
- <translation>否</translation>
- </message>
- <message>
<source>Unknown</source>
<translation>不明</translation>
</message>
@@ -1897,7 +2113,7 @@
</message>
<message>
<source>An optional label to associate with the new receiving address.</source>
- <translation>跟新收款位址關聯的標記,可以不填。</translation>
+ <translation>與新的接收地址關聯的可選的標籤。</translation>
</message>
<message>
<source>Use this form to request payments. All fields are &lt;b&gt;optional&lt;/b&gt;.</source>
@@ -1908,8 +2124,16 @@
<translation>要求付款的金額,可以不填。不確定金額時可以留白或是填零。</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>與新的接收地址相關聯的可選的標籤(您用於標識收據)。它也附在支付支付請求上。</translation>
+ </message>
+ <message>
+ <source>An optional message that is attached to the payment request and may be displayed to the sender.</source>
+ <translation>附加在支付請求上的可選的訊息,可以顯示給發送者。</translation>
+ </message>
+ <message>
<source>&amp;Create new receiving address</source>
- <translation>&amp;生成新的接收位址</translation>
+ <translation>&amp;產生新的接收地址</translation>
</message>
<message>
<source>Clear all fields of the form.</source>
@@ -1921,11 +2145,11 @@
</message>
<message>
<source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source>
- <translation>使用 segwit 原生位址(也叫做 Bech32 或 BIP-173)可以減少日後的交易手續費,也比較不容易打錯字,不過會跟舊版的錢包軟體不相容。如果沒有勾選的話,會改產生與舊版錢包軟體相容的位址。</translation>
+ <translation>使用原生的隔離見證地址(也叫做 Bech32 或 BIP-173)可以減少日後的交易手續費,並能更好地防止輸入錯誤,不過會跟舊版的錢包軟體不支援。如果沒有勾選的話,會改產生與舊版錢包軟體相容的地址。</translation>
</message>
<message>
<source>Generate native segwit (Bech32) address</source>
- <translation>產生 segwit 原生位址(Bech32)</translation>
+ <translation>產生原生隔離見證(Bech32)地址</translation>
</message>
<message>
<source>Requested payments history</source>
@@ -1963,56 +2187,56 @@
<source>Copy amount</source>
<translation>複製金額</translation>
</message>
-</context>
-<context>
- <name>ReceiveRequestDialog</name>
<message>
- <source>QR Code</source>
- <translation>QR Code</translation>
+ <source>Could not unlock wallet.</source>
+ <translation>沒辦法把錢包解鎖。</translation>
</message>
+ </context>
+<context>
+ <name>ReceiveRequestDialog</name>
<message>
- <source>Copy &amp;URI</source>
- <translation>複製 &amp;URI</translation>
+ <source>Request payment to ...</source>
+ <translation>請求付款給...</translation>
</message>
<message>
- <source>Copy &amp;Address</source>
- <translation>複製位址(&amp;A)</translation>
+ <source>Address:</source>
+ <translation>地址:</translation>
</message>
<message>
- <source>&amp;Save Image...</source>
- <translation>儲存圖片(&amp;S)...</translation>
+ <source>Amount:</source>
+ <translation>金額:</translation>
</message>
<message>
- <source>Request payment to %1</source>
- <translation>付款給 %1 的要求</translation>
+ <source>Label:</source>
+ <translation>標記:</translation>
</message>
<message>
- <source>Payment information</source>
- <translation>付款資訊</translation>
+ <source>Message:</source>
+ <translation>訊息:</translation>
</message>
<message>
- <source>URI</source>
- <translation>URI</translation>
+ <source>Wallet:</source>
+ <translation>錢包:</translation>
</message>
<message>
- <source>Address</source>
- <translation>位址</translation>
+ <source>Copy &amp;URI</source>
+ <translation>複製 &amp;URI</translation>
</message>
<message>
- <source>Amount</source>
- <translation>金額</translation>
+ <source>Copy &amp;Address</source>
+ <translation>複製 &amp;地址</translation>
</message>
<message>
- <source>Label</source>
- <translation>標記:</translation>
+ <source>&amp;Save Image...</source>
+ <translation>儲存圖片(&amp;S)...</translation>
</message>
<message>
- <source>Message</source>
- <translation>訊息</translation>
+ <source>Request payment to %1</source>
+ <translation>付款給 %1 的要求</translation>
</message>
<message>
- <source>Wallet</source>
- <translation>錢包</translation>
+ <source>Payment information</source>
+ <translation>付款資訊</translation>
</message>
</context>
<context>
@@ -2094,7 +2318,7 @@
</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>如果這項有打開,但是找零位址是空的或無效,那麼找零的錢會送到一個新造出來的位址去。</translation>
+ <translation>如果這項有打開,但是找零地址是空的或無效,那麼找零會送到一個產生出來的地址去。</translation>
</message>
<message>
<source>Custom change address</source>
@@ -2161,6 +2385,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>零散錢:</translation>
</message>
<message>
+ <source>Hide transaction fee settings</source>
+ <translation>隱藏交易手續費設定</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>当交易量小于可用区块空间时,矿工和中继节点可能会执行最低手续费率限制。按照这个最低费率来支付手续费也是可以的,但请注意,一旦交易需求超出比特币网络能处理的限度,你的交易可能永远也无法确认。</translation>
</message>
@@ -2229,6 +2457,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%1 (%2 個區塊)</translation>
</message>
<message>
+ <source>Cr&amp;eate Unsigned</source>
+ <translation>Cr&eate未簽名</translation>
+ </message>
+ <message>
<source> from wallet '%1'</source>
<translation>從錢包 %1</translation>
</message>
@@ -2241,10 +2473,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%1 給 %2</translation>
</message>
<message>
+ <source>Do you want to draft this transaction?</source>
+ <translation>您要草擬此交易嗎?</translation>
+ </message>
+ <message>
<source>Are you sure you want to send?</source>
<translation>你確定要付錢出去嗎?</translation>
</message>
<message>
+ <source>Create Unsigned</source>
+ <translation>產生未簽名</translation>
+ </message>
+ <message>
+ <source>Save Transaction Data</source>
+ <translation>儲存交易資料</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (Binary) (*.psbt)</source>
+ <translation>部分簽名的交易(二進制)(* .psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT saved</source>
+ <translation>PSBT已儲存</translation>
+ </message>
+ <message>
<source>or</source>
<translation>或</translation>
</message>
@@ -2277,12 +2529,20 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>確認付款金額</translation>
</message>
<message>
+ <source>Confirm transaction proposal</source>
+ <translation>確認交易建議</translation>
+ </message>
+ <message>
<source>Send</source>
<translation>發</translation>
</message>
<message>
+ <source>Watch-only balance:</source>
+ <translation>只能看餘額:</translation>
+ </message>
+ <message>
<source>The recipient address is not valid. Please recheck.</source>
- <translation>收款位址無效。請再檢查看看。</translation>
+ <translation>接受者地址無效。請再檢查看看。</translation>
</message>
<message>
<source>The amount to pay must be larger than 0.</source>
@@ -2298,7 +2558,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Duplicate address found: addresses should only be used once each.</source>
- <translation>發現有重複的位址: 每個位址只能出現一次。</translation>
+ <translation>發現有重複的地址: 每個地址只能出現一次。</translation>
</message>
<message>
<source>Transaction creation failed!</source>
@@ -2318,19 +2578,19 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Warning: Invalid Bitcoin address</source>
- <translation>警告: Bitcoin 位址無效</translation>
+ <translation>警告: 比特幣地址無效</translation>
</message>
<message>
<source>Warning: Unknown change address</source>
- <translation>警告: 不明的找零位址</translation>
+ <translation>警告: 未知的找零地址</translation>
</message>
<message>
<source>Confirm custom change address</source>
- <translation>自定找零位址確認</translation>
+ <translation>確認自訂找零地址</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>選擇的找零位址並不屬於這個錢包。部份或是全部的錢會被送到這個位址去。你確定嗎?</translation>
+ <translation>選擇的找零地址並不屬於這個錢包。部份或是全部的錢會被送到這個地址去。你確定嗎?</translation>
</message>
<message>
<source>(no label)</source>
@@ -2353,11 +2613,11 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Choose previously used address</source>
- <translation>選擇先前使用過的位址</translation>
+ <translation>選擇先前使用過的地址</translation>
</message>
<message>
<source>The Bitcoin address to send the payment to</source>
- <translation>接收付款的 Bitcoin 位址</translation>
+ <translation>將支付發送到的比特幣地址給</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2365,7 +2625,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Paste address from clipboard</source>
- <translation>貼上剪貼簿裡的位址</translation>
+ <translation>貼上剪貼簿裡的地址</translation>
</message>
<message>
<source>Alt+P</source>
@@ -2376,6 +2636,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>刪掉這個項目</translation>
</message>
<message>
+ <source>The amount to send in the selected unit</source>
+ <translation>以所選單位發送的金額</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>手續費會從要付款出去的金額中扣掉。因此收款人會收到比輸入的金額還要少的 bitcoin。如果有多個收款人的話,手續費會平均分配來扣除。</translation>
</message>
@@ -2401,7 +2665,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Enter a label for this address to add it to the list of used addresses</source>
- <translation>請輸入這個位址的標記,來把它加進去已使用過位址的清單。</translation>
+ <translation>請輸入這個地址的標籤,來把它加進去已使用過地址清單。</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>
@@ -2439,15 +2703,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>你可以用自己的位址簽署訊息或合約,來證明你可以從該位址收款。但是請小心,不要簽署語意含糊不清,或隨機產生的內容,因為釣魚式詐騙可能會用騙你簽署的手法來冒充是你。只有在語句中的細節你都同意時才簽署。</translation>
+ <translation>您可以使用您的地址簽名訊息/協議,以證明您可以接收發送給他們的比特幣。但是請小心,不要簽名語意含糊不清,或隨機產生的內容,因為釣魚式詐騙可能會用騙你簽名的手法來冒充是你。只有簽名您同意的詳細內容。</translation>
</message>
<message>
<source>The Bitcoin address to sign the message with</source>
- <translation>用來簽署訊息的 Bitcoin 位址</translation>
+ <translation>用來簽名訊息的 比特幣地址</translation>
</message>
<message>
<source>Choose previously used address</source>
- <translation>選擇先前使用過的位址</translation>
+ <translation>選擇先前使用過的地址</translation>
</message>
<message>
<source>Alt+A</source>
@@ -2455,7 +2719,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Paste address from clipboard</source>
- <translation>貼上剪貼簿裡的位址</translation>
+ <translation>貼上剪貼簿裡的地址</translation>
</message>
<message>
<source>Alt+P</source>
@@ -2475,7 +2739,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Sign the message to prove you own this Bitcoin address</source>
- <translation>簽署這個訊息來證明這個 Bitcoin 位址是你的</translation>
+ <translation>簽名這個訊息來證明這個比特幣地址是你的</translation>
</message>
<message>
<source>Sign &amp;Message</source>
@@ -2495,15 +2759,23 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</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>請在下面輸入收款人的位址,訊息(請確定完整複製了所包含的換行,空格,跳位符號等等),以及簽章,來驗證這個訊息。請小心,除了訊息內容以外,不要對簽章本身過度解讀,以避免被用「中間人攻擊法」詐騙。請注意,通過驗證的簽章只能證明簽章人確實可以從該位址收款,不能證明任何交易中的付款人身份!</translation>
+ <translation>請在下面輸入收款人的地址,訊息(請確定完整複製了所包含的換行、空格、tabs...等),以及簽名,來驗證這個訊息。請小心,除了訊息內容以外,不要對簽名本身過度解讀,以避免被用「中間人攻擊法」詐騙。請注意,通過驗證的簽名只能證明簽名人確實可以從該地址收款,不能證明任何交易中的付款人身份!</translation>
</message>
<message>
<source>The Bitcoin address the message was signed with</source>
- <translation>簽署這個訊息的 Bitcoin 位址</translation>
+ <translation>簽名這個訊息的 比特幣地址</translation>
+ </message>
+ <message>
+ <source>The signed message to verify</source>
+ <translation>簽名訊息進行驗證</translation>
+ </message>
+ <message>
+ <source>The signature given when the message was signed</source>
+ <translation>簽名訊息時給出的簽名</translation>
</message>
<message>
<source>Verify the message to ensure it was signed with the specified Bitcoin address</source>
- <translation>驗證這個訊息來確定是用指定的 Bitcoin 位址簽署的</translation>
+ <translation>驗證這個訊息來確定是用指定的比特幣地址簽名的</translation>
</message>
<message>
<source>Verify &amp;Message</source>
@@ -2519,15 +2791,15 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>The entered address is invalid.</source>
- <translation>輸入的位址無效。</translation>
+ <translation>輸入的地址無效。</translation>
</message>
<message>
<source>Please check the address and try again.</source>
- <translation>請檢查位址是否正確後再試一次。</translation>
+ <translation>請檢查地址是否正確後再試一次。</translation>
</message>
<message>
<source>The entered address does not refer to a key.</source>
- <translation>輸入的位址沒有對應到你的任何密鑰。</translation>
+ <translation>輸入的地址沒有對應到你的任何鑰匙。</translation>
</message>
<message>
<source>Wallet unlock was cancelled.</source>
@@ -2539,7 +2811,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Private key for the entered address is not available.</source>
- <translation>沒有對應輸入位址的密鑰。</translation>
+ <translation>沒有對應輸入地址的私鑰。</translation>
</message>
<message>
<source>Message signing failed.</source>
@@ -2645,7 +2917,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>own address</source>
- <translation>自己的位址</translation>
+ <translation>自己的地址</translation>
</message>
<message>
<source>watch-only</source>
@@ -2712,6 +2984,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>輸出索引</translation>
</message>
<message>
+ <source> (Certificate was not verified)</source>
+ <translation>(證書未驗證)</translation>
+ </message>
+ <message>
<source>Merchant</source>
<translation>商家</translation>
</message>
@@ -2851,7 +3127,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Whether or not a watch-only address is involved in this transaction.</source>
- <translation>不論如何有一個只能觀看的地只有參與這次的交易</translation>
+ <translation>此交易是否涉及監視地址。</translation>
</message>
<message>
<source>User-defined intent/purpose of the transaction.</source>
@@ -2914,7 +3190,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Enter address, transaction id, or label to search</source>
- <translation>請輸入要搜尋的位址、交易識別碼、或是標記</translation>
+ <translation>請輸入要搜尋的地址、交易 ID、或是標記標籤</translation>
</message>
<message>
<source>Min amount</source>
@@ -2930,7 +3206,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Copy address</source>
- <translation>複製位址</translation>
+ <translation>複製地址</translation>
</message>
<message>
<source>Copy label</source>
@@ -2990,7 +3266,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Address</source>
- <translation>位址</translation>
+ <translation>地址</translation>
</message>
<message>
<source>ID</source>
@@ -3038,12 +3314,28 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<source>Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled.</source>
<translation>關上錢包太久的話且修剪模式又有開啟的話,可能會造成日後需要重新同步整個區塊鏈。</translation>
</message>
+ <message>
+ <source>Close all wallets</source>
+ <translation>關閉所有錢包</translation>
+ </message>
+ <message>
+ <source>Are you sure you wish to close all wallets?</source>
+ <translation>您確定要關閉所有錢包嗎?</translation>
+ </message>
</context>
<context>
<name>WalletFrame</name>
<message>
- <source>No wallet has been loaded.</source>
- <translation>沒有載入錢包。</translation>
+ <source>No wallet has been loaded.
+Go to File &gt; Open Wallet to load a wallet.
+- OR -</source>
+ <translation>尚未載入任何錢包。
+轉到檔案 &gt; 開啟錢包以載入錢包.
+- OR -</translation>
+ </message>
+ <message>
+ <source>Create a new wallet</source>
+ <translation>創建一個新錢包</translation>
</message>
</context>
<context>
@@ -3065,6 +3357,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>想要提高手續費嗎?</translation>
</message>
<message>
+ <source>Do you want to draft a transaction with fee increase?</source>
+ <translation>您想通過增加手續費草擬交易嗎?</translation>
+ </message>
+ <message>
<source>Current fee:</source>
<translation>目前費用:</translation>
</message>
@@ -3081,6 +3377,14 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>確認手續費提升</translation>
</message>
<message>
+ <source>Can't draft transaction.</source>
+ <translation>無法草擬交易。</translation>
+ </message>
+ <message>
+ <source>PSBT copied</source>
+ <translation>PSBT已復制</translation>
+ </message>
+ <message>
<source>Can't sign transaction.</source>
<translation>沒辦法簽署交易。</translation>
</message>
@@ -3104,6 +3408,30 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>將目前分頁的資料匯出存成檔案</translation>
</message>
<message>
+ <source>Error</source>
+ <translation>錯誤</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT from clipboard (invalid base64)</source>
+ <translation>無法從剪貼板解碼PSBT(無效的base64)</translation>
+ </message>
+ <message>
+ <source>Load Transaction Data</source>
+ <translation>載入交易資料</translation>
+ </message>
+ <message>
+ <source>Partially Signed Transaction (*.psbt)</source>
+ <translation>簽名部分的交易(* .psbt)</translation>
+ </message>
+ <message>
+ <source>PSBT file must be smaller than 100 MiB</source>
+ <translation>PSBT檔案必須小於100 MiB</translation>
+ </message>
+ <message>
+ <source>Unable to decode PSBT</source>
+ <translation>無法解碼PSBT</translation>
+ </message>
+ <message>
<source>Backup Wallet</source>
<translation>備份錢包</translation>
</message>
@@ -3147,10 +3475,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>修剪模式:錢包的最後同步狀態是在被修剪掉的區塊資料中。你需要用 -reindex 參數執行(會重新下載整個區塊鏈)</translation>
</message>
<message>
- <source>Error: A fatal internal error occurred, see debug.log for details</source>
- <translation>錯誤: 發生了致命的內部錯誤,詳情請看 debug.log</translation>
- </message>
- <message>
<source>Pruning blockstore...</source>
<translation>正在修剪區塊資料庫中...</translation>
</message>
@@ -3163,10 +3487,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>%s 開發人員</translation>
</message>
<message>
- <source>Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.</source>
- <translation>无法生成找零地址密钥。 内部密钥池中没有密钥,也无法生成任何密钥。</translation>
- </message>
- <message>
<source>Cannot obtain a lock on data directory %s. %s is probably already running.</source>
<translation>沒辦法鎖定資料目錄 %s。%s 可能已經在執行了。</translation>
</message>
@@ -3176,7 +3496,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Error reading %s! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <translation>讀取錢包檔 %s 時發生錯誤!所有的密鑰都正確讀取了,但是交易資料或位址簿資料可能會缺少或不正確。</translation>
+ <translation>讀取錢包檔 %s 時發生錯誤!所有的鑰匙都正確讀取了,但是交易資料或地址簿資料可能會缺少或不正確。</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>
@@ -3215,20 +3535,12 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>警告: 我們和某些連線的節點對於區塊鏈結的決定不同!你可能需要升級,或是需要等其它的節點升級。</translation>
</message>
<message>
- <source>%d of last 100 blocks have unexpected version</source>
- <translation>最近的 100 個區塊中有 %d 個意料之外的區塊版本</translation>
- </message>
- <message>
- <source>%s corrupt, salvage failed</source>
- <translation>錢包檔 %s 壞掉了,搶救失敗</translation>
- </message>
- <message>
<source>-maxmempool must be at least %d MB</source>
<translation>參數 -maxmempool 至少要給 %d 百萬位元組(MB)</translation>
</message>
<message>
<source>Cannot resolve -%s address: '%s'</source>
- <translation>沒辦法解析 -%s 參數指定的位址: '%s'</translation>
+ <translation>沒辦法解析 -%s 參數指定的地址: '%s'</translation>
</message>
<message>
<source>Change index out of range</source>
@@ -3324,7 +3636,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Unknown address type '%s'</source>
- <translation>不明的位址類型 '%s'</translation>
+ <translation>未知的地址類型 '%s'</translation>
</message>
<message>
<source>Unknown change type '%s'</source>
@@ -3336,11 +3648,7 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
</message>
<message>
<source>Loading P2P addresses...</source>
- <translation>正在載入 P2P 位址資料...</translation>
- </message>
- <message>
- <source>Error: Disk space is too low!</source>
- <translation>錯誤: 磁碟空間很少!</translation>
+ <translation>正在載入 P2P 地址資料...</translation>
</message>
<message>
<source>Loading banlist...</source>
@@ -3407,6 +3715,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>錯誤: 聽候外來連線失敗(回傳錯誤 %s)</translation>
</message>
<message>
+ <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.</source>
+ <translation>如果不升級以支援預拆分keypool,則無法升級非HD拆分錢包。請使用169900版本或沒有版本。</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>-maxtxfee=&lt;amount&gt;: '%s' 的金額無效 (必須大於最低轉發手續費 %s 以避免交易無法確認)</translation>
</message>
@@ -3415,10 +3727,34 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>扣除手續費後的交易金額太少而不能傳送</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>如果未完全關閉該錢包,並且最後一次使用具有較新版本的Berkeley DB的構建載入了此錢包,則可能會發生此錯誤。如果是這樣,請使用最後載入該錢包的軟體</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>這是您支付的最高交易手續費(除了正常手續費外),優先於避免部分花費而不是定期選取幣。</translation>
+ </message>
+ <message>
+ <source>Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.</source>
+ <translation>交易需要變更地址,但我們無法產生它。請先呼叫keypoolrefill。</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>回到非修剪的模式需要用 -reindex 參數來重建資料庫。這會導致重新下載整個區塊鏈。</translation>
</message>
<message>
+ <source>A fatal internal error occurred, see debug.log for details</source>
+ <translation>發生致命的內部錯誤,有關詳細細節,請參見debug.log</translation>
+ </message>
+ <message>
+ <source>Cannot set -peerblockfilters without -blockfilterindex.</source>
+ <translation>在沒有設定-blockfilterindex 則無法使用 -peerblockfilters</translation>
+ </message>
+ <message>
+ <source>Disk space is too low!</source>
+ <translation>硬碟空間太小!</translation>
+ </message>
+ <message>
<source>Error reading from database, shutting down.</source>
<translation>讀取資料庫時發生錯誤,要關閉了。</translation>
</message>
@@ -3431,12 +3767,16 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>错误: %s 所在的磁盘空间低。</translation>
</message>
<message>
+ <source>Error: Keypool ran out, please call keypoolrefill first</source>
+ <translation>錯誤:keypool已用完,請先重新呼叫keypoolrefill</translation>
+ </message>
+ <message>
<source>Invalid -onion address or hostname: '%s'</source>
- <translation>無效的 -onion 位址或主機名稱: '%s'</translation>
+ <translation>無效的 -onion 地址或主機名稱: '%s'</translation>
</message>
<message>
<source>Invalid -proxy address or hostname: '%s'</source>
- <translation>無效的 -proxy 位址或主機名稱: '%s'</translation>
+ <translation>無效的 -proxy 地址或主機名稱: '%s'</translation>
</message>
<message>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: '%s' (must be at least %s)</source>
@@ -3451,6 +3791,10 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>指定 -whitebind 時必須包含通訊埠: '%s'</translation>
</message>
<message>
+ <source>No proxy server specified. Use -proxy=&lt;ip&gt; or -proxy=&lt;ip:port&gt;.</source>
+ <translation>未指定代理伺服器。使用-proxy = &lt;ip&gt;或-proxy = &lt;ip:port&gt;。</translation>
+ </message>
+ <message>
<source>Prune mode is incompatible with -blockfilterindex.</source>
<translation>修剪模式與 -blockfilterindex不相容。</translation>
</message>
@@ -3525,10 +3869,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>警告: 不明的交易規則被啟用了(versionbit %i)</translation>
</message>
<message>
- <source>Zapping all transactions from wallet...</source>
- <translation>正在砍掉錢包中的所有交易...</translation>
- </message>
- <message>
<source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
<translation>參數 -maxtxfee 設定了很高的金額!這可是你一次交易就有可能付出的最高手續費。</translation>
</message>
@@ -3541,10 +3881,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>網路版本字串的總長度(%i)超過最大長度(%i)了。請減少 uacomment 參數的數目或長度。</translation>
</message>
<message>
- <source>Warning: Wallet file corrupt, data salvaged! Original %s saved as %s in %s; if your balance or transactions are incorrect you should restore from a backup.</source>
- <translation>警告: 錢包檔壞掉,但資料被救回來了!原來的檔案 %s 改儲存為 %s,在目錄 %s 下。 如果餘額或交易資料有誤的話,你應該要從備份資料復原回來。</translation>
- </message>
- <message>
<source>%s is set very high!</source>
<translation>%s 的設定值異常大!</translation>
</message>
@@ -3589,10 +3925,6 @@ Note: Since the fee is calculated on a per-byte basis, a fee of "100 satoshis p
<translation>累積金額不足</translation>
</message>
<message>
- <source>Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use -upgradewallet=169900 or -upgradewallet with no version specified.</source>
- <translation>無法將一個非 HD 分支錢包升級成不支援預先分支密鑰池的 HD 分支錢包版本。請用 -upgradewallet=169900 參數或是不指定版本的 -upgradewallet 參數來升級錢包。</translation>
- </message>
- <message>
<source>Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.</source>
<translation>計算預估手續費失敗了,也沒有備用手續費(fallbackfee)可用。請再多等待幾個區塊,或是啟用 -fallbackfee 參數。</translation>
</message>
diff --git a/src/qt/locale/bitcoin_zu.ts b/src/qt/locale/bitcoin_zu.ts
index 30e7bec4b9..0ff40282a3 100644
--- a/src/qt/locale/bitcoin_zu.ts
+++ b/src/qt/locale/bitcoin_zu.ts
@@ -46,10 +46,6 @@
<translation>Lawa amakheli akho e-Bitcoin okuthumela izinkokhelo. Njalo hlola inani nekheli elitholwayo ngaphambi kokuthumela izinhlamvu zemali.</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.</source>
- <translation>Lawa amakheli akho e-Bitcoin athola izinkokhelo. Sebenzisa inkinobho ethi 'Dala ikheli elisha lokuthola' kuthebhu yokwamukela ukudala amakheli amasha.</translation>
- </message>
- <message>
<source>Export Address List</source>
<translation>Thumela Ikheli Langaphandle</translation>
</message>
@@ -184,6 +180,9 @@ Lahla YONKE IBITCOIN YAKHO!</translation>
<name>OverviewPage</name>
</context>
<context>
+ <name>PSBTOperationsDialog</name>
+ </context>
+<context>
<name>PaymentServer</name>
</context>
<context>
@@ -203,14 +202,6 @@ Lahla YONKE IBITCOIN YAKHO!</translation>
</context>
<context>
<name>ReceiveRequestDialog</name>
- <message>
- <source>Address</source>
- <translation>Ikheli</translation>
- </message>
- <message>
- <source>Label</source>
- <translation>Ilebuli</translation>
- </message>
</context>
<context>
<name>RecentRequestsTableModel</name>
diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp
index 4b91c19761..d518a2065c 100644
--- a/src/qt/notificator.cpp
+++ b/src/qt/notificator.cpp
@@ -17,12 +17,7 @@
#include <stdint.h>
#include <QtDBus>
#endif
-// Include ApplicationServices.h after QtDbus to avoid redefinition of check().
-// This affects at least OSX 10.6. See /usr/include/AssertMacros.h for details.
-// Note: This could also be worked around using:
-// #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
#ifdef Q_OS_MAC
-#include <ApplicationServices/ApplicationServices.h>
#include <qt/macnotificationhandler.h>
#endif
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index ae6aeb7709..78d4dd5557 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -130,8 +130,8 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
connect(ui->proxyPortTor, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
- ui->hideTrayIcon->setChecked(true);
- ui->hideTrayIcon->setEnabled(false);
+ ui->showTrayIcon->setChecked(false);
+ ui->showTrayIcon->setEnabled(false);
ui->minimizeToTray->setChecked(false);
ui->minimizeToTray->setEnabled(false);
}
@@ -227,7 +227,7 @@ void OptionsDialog::setMapper()
/* Window */
#ifndef Q_OS_MAC
if (QSystemTrayIcon::isSystemTrayAvailable()) {
- mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon);
+ mapper->addMapping(ui->showTrayIcon, OptionsModel::ShowTrayIcon);
mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
}
mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
@@ -286,17 +286,14 @@ void OptionsDialog::on_cancelButton_clicked()
reject();
}
-void OptionsDialog::on_hideTrayIcon_stateChanged(int fState)
+void OptionsDialog::on_showTrayIcon_stateChanged(int state)
{
- if(fState)
- {
+ if (state == Qt::Checked) {
+ ui->minimizeToTray->setEnabled(true);
+ } else {
ui->minimizeToTray->setChecked(false);
ui->minimizeToTray->setEnabled(false);
}
- else
- {
- ui->minimizeToTray->setEnabled(true);
- }
}
void OptionsDialog::togglePruneWarning(bool enabled)
diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h
index 568c8b6fd0..3a7b9192a1 100644
--- a/src/qt/optionsdialog.h
+++ b/src/qt/optionsdialog.h
@@ -57,7 +57,7 @@ private Q_SLOTS:
void on_okButton_clicked();
void on_cancelButton_clicked();
- void on_hideTrayIcon_stateChanged(int fState);
+ void on_showTrayIcon_stateChanged(int state);
void togglePruneWarning(bool enabled);
void showRestartWarning(bool fPersistent = false);
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 7e089b4f95..152de6decb 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -54,14 +54,15 @@ void OptionsModel::Init(bool resetSettings)
// These are Qt-only settings:
// Window
- if (!settings.contains("fHideTrayIcon"))
+ if (!settings.contains("fHideTrayIcon")) {
settings.setValue("fHideTrayIcon", false);
- fHideTrayIcon = settings.value("fHideTrayIcon").toBool();
- Q_EMIT hideTrayIconChanged(fHideTrayIcon);
+ }
+ m_show_tray_icon = !settings.value("fHideTrayIcon").toBool();
+ Q_EMIT showTrayIconChanged(m_show_tray_icon);
if (!settings.contains("fMinimizeToTray"))
settings.setValue("fMinimizeToTray", false);
- fMinimizeToTray = settings.value("fMinimizeToTray").toBool() && !fHideTrayIcon;
+ fMinimizeToTray = settings.value("fMinimizeToTray").toBool() && m_show_tray_icon;
if (!settings.contains("fMinimizeOnClose"))
settings.setValue("fMinimizeOnClose", false);
@@ -219,7 +220,7 @@ static ProxySetting GetProxySetting(QSettings &settings, const QString &name)
return default_val;
}
// contains IP at index 0 and port at index 1
- QStringList ip_port = settings.value(name).toString().split(":", QString::SkipEmptyParts);
+ QStringList ip_port = GUIUtil::SplitSkipEmptyParts(settings.value(name).toString(), ":");
if (ip_port.size() == 2) {
return {true, ip_port.at(0), ip_port.at(1)};
} else { // Invalid: return default
@@ -272,8 +273,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
{
case StartAtStartup:
return GUIUtil::GetStartOnSystemStartup();
- case HideTrayIcon:
- return fHideTrayIcon;
+ case ShowTrayIcon:
+ return m_show_tray_icon;
case MinimizeToTray:
return fMinimizeToTray;
case MapPortUPnP:
@@ -342,10 +343,10 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
case StartAtStartup:
successful = GUIUtil::SetStartOnSystemStartup(value.toBool());
break;
- case HideTrayIcon:
- fHideTrayIcon = value.toBool();
- settings.setValue("fHideTrayIcon", fHideTrayIcon);
- Q_EMIT hideTrayIconChanged(fHideTrayIcon);
+ case ShowTrayIcon:
+ m_show_tray_icon = value.toBool();
+ settings.setValue("fHideTrayIcon", !m_show_tray_icon);
+ Q_EMIT showTrayIconChanged(m_show_tray_icon);
break;
case MinimizeToTray:
fMinimizeToTray = value.toBool();
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index 3d9e7bbb80..f1929a5e06 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -45,7 +45,7 @@ public:
enum OptionID {
StartAtStartup, // bool
- HideTrayIcon, // bool
+ ShowTrayIcon, // bool
MinimizeToTray, // bool
MapPortUPnP, // bool
MinimizeOnClose, // bool
@@ -78,7 +78,7 @@ public:
void setDisplayUnit(const QVariant &value);
/* Explicit getters */
- bool getHideTrayIcon() const { return fHideTrayIcon; }
+ bool getShowTrayIcon() const { return m_show_tray_icon; }
bool getMinimizeToTray() const { return fMinimizeToTray; }
bool getMinimizeOnClose() const { return fMinimizeOnClose; }
int getDisplayUnit() const { return nDisplayUnit; }
@@ -100,7 +100,7 @@ public:
private:
interfaces::Node* m_node = nullptr;
/* Qt-only settings */
- bool fHideTrayIcon;
+ bool m_show_tray_icon;
bool fMinimizeToTray;
bool fMinimizeOnClose;
QString language;
@@ -118,7 +118,7 @@ private:
Q_SIGNALS:
void displayUnitChanged(int unit);
void coinControlFeaturesChanged(bool);
- void hideTrayIconChanged(bool);
+ void showTrayIconChanged(bool);
};
#endif // BITCOIN_QT_OPTIONSMODEL_H
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index b536567c8b..1297eb8b75 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -17,6 +17,7 @@
#include <QAbstractItemDelegate>
#include <QApplication>
+#include <QDateTime>
#include <QPainter>
#include <QStatusTipEvent>
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 6c2db52f63..86d681aa6f 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -26,7 +26,6 @@
#include <QApplication>
#include <QByteArray>
#include <QDataStream>
-#include <QDateTime>
#include <QDebug>
#include <QFile>
#include <QFileOpenEvent>
diff --git a/src/qt/qrimagewidget.cpp b/src/qt/qrimagewidget.cpp
index c816e1f8ed..141f4abb3b 100644
--- a/src/qt/qrimagewidget.cpp
+++ b/src/qt/qrimagewidget.cpp
@@ -9,6 +9,7 @@
#include <QApplication>
#include <QClipboard>
#include <QDrag>
+#include <QFontDatabase>
#include <QMenu>
#include <QMimeData>
#include <QMouseEvent>
@@ -64,26 +65,28 @@ bool QRImageWidget::setQR(const QString& data, const QString& text)
}
QRcode_free(code);
- QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE + (text.isEmpty() ? 0 : 20), QImage::Format_RGB32);
+ const int qr_image_size = QR_IMAGE_SIZE + (text.isEmpty() ? 0 : 2 * QR_IMAGE_MARGIN);
+ QImage qrAddrImage(qr_image_size, qr_image_size, QImage::Format_RGB32);
qrAddrImage.fill(0xffffff);
- QPainter painter(&qrAddrImage);
- painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));
+ {
+ QPainter painter(&qrAddrImage);
+ painter.drawImage(QR_IMAGE_MARGIN, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));
- if (!text.isEmpty()) {
- QFont font = GUIUtil::fixedPitchFont();
- font.setStyleStrategy(QFont::NoAntialias);
- QRect paddedRect = qrAddrImage.rect();
+ if (!text.isEmpty()) {
+ QRect paddedRect = qrAddrImage.rect();
+ paddedRect.setHeight(QR_IMAGE_SIZE + QR_IMAGE_TEXT_MARGIN);
- // calculate ideal font size
- qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 20, text, font);
- font.setPointSizeF(font_size);
+ QFont font = GUIUtil::fixedPitchFont();
+ font.setStretch(QFont::SemiCondensed);
+ font.setLetterSpacing(QFont::AbsoluteSpacing, 1);
+ const qreal font_size = GUIUtil::calculateIdealFontSize(paddedRect.width() - 2 * QR_IMAGE_TEXT_MARGIN, text, font);
+ font.setPointSizeF(font_size);
- painter.setFont(font);
- paddedRect.setHeight(QR_IMAGE_SIZE+12);
- painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, text);
+ painter.setFont(font);
+ painter.drawText(paddedRect, Qt::AlignBottom | Qt::AlignCenter, text);
+ }
}
- painter.end();
setPixmap(QPixmap::fromImage(qrAddrImage));
return true;
@@ -95,15 +98,12 @@ bool QRImageWidget::setQR(const QString& data, const QString& text)
QImage QRImageWidget::exportImage()
{
- if(!pixmap())
- return QImage();
- return pixmap()->toImage();
+ return GUIUtil::GetImage(this);
}
void QRImageWidget::mousePressEvent(QMouseEvent *event)
{
- if(event->button() == Qt::LeftButton && pixmap())
- {
+ if (event->button() == Qt::LeftButton && GUIUtil::HasPixmap(this)) {
event->accept();
QMimeData *mimeData = new QMimeData;
mimeData->setImageData(exportImage());
@@ -118,7 +118,7 @@ void QRImageWidget::mousePressEvent(QMouseEvent *event)
void QRImageWidget::saveImage()
{
- if(!pixmap())
+ if (!GUIUtil::HasPixmap(this))
return;
QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Image (*.png)"), nullptr);
if (!fn.isEmpty())
@@ -129,14 +129,14 @@ void QRImageWidget::saveImage()
void QRImageWidget::copyImage()
{
- if(!pixmap())
+ if (!GUIUtil::HasPixmap(this))
return;
QApplication::clipboard()->setImage(exportImage());
}
void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
{
- if(!pixmap())
+ if (!GUIUtil::HasPixmap(this))
return;
contextMenu->exec(event->globalPos());
}
diff --git a/src/qt/qrimagewidget.h b/src/qt/qrimagewidget.h
index cca598c2ce..a031bd7632 100644
--- a/src/qt/qrimagewidget.h
+++ b/src/qt/qrimagewidget.h
@@ -12,7 +12,9 @@
static const int MAX_URI_LENGTH = 255;
/* Size of exported QR Code image */
-static const int QR_IMAGE_SIZE = 300;
+static constexpr int QR_IMAGE_SIZE = 300;
+static constexpr int QR_IMAGE_TEXT_MARGIN = 10;
+static constexpr int QR_IMAGE_MARGIN = 2 * QR_IMAGE_TEXT_MARGIN;
QT_BEGIN_NAMESPACE
class QMenu;
diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc
index 94ae256477..e590b407b0 100644
--- a/src/qt/res/bitcoin-qt-res.rc
+++ b/src/qt/res/bitcoin-qt-res.rc
@@ -4,8 +4,8 @@ IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico"
#include <windows.h> // needed for VERSIONINFO
#include "../../clientversion.h" // holds the needed client version information
-#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD
-#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD)
+#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_BUILD
+#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_BUILD)
#define VER_FILEVERSION VER_PRODUCTVERSION
#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4c5601242e..236c6e13d5 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -25,10 +25,14 @@
#include <univalue.h>
#ifdef ENABLE_WALLET
+#ifdef USE_BDB
+#include <wallet/bdb.h>
+#endif
#include <wallet/db.h>
#include <wallet/wallet.h>
#endif
+#include <QDateTime>
#include <QFont>
#include <QKeyEvent>
#include <QMenu>
@@ -479,13 +483,6 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
ui->WalletSelector->setVisible(false);
ui->WalletSelectorLabel->setVisible(false);
- // set library version labels
-#ifdef ENABLE_WALLET
- ui->berkeleyDBVersion->setText(QString::fromStdString(BerkeleyDatabaseVersion()));
-#else
- ui->label_berkeleyDBVersion->hide();
- ui->berkeleyDBVersion->hide();
-#endif
// Register RPC timer interface
rpcTimerInterface = new QtRPCTimerInterface();
// avoid accidentally overwriting an existing, non QTThread
@@ -493,9 +490,7 @@ RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformSty
m_node.rpcSetTimerInterfaceIfUnset(rpcTimerInterface);
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
-
- ui->detailWidget->hide();
- ui->peerHeading->setText(tr("Select a peer to view detailed information."));
+ updateDetailWidget();
consoleFontSize = settings.value(fontSizeSettingsKey, QFont().pointSize()).toInt();
clear();
@@ -626,7 +621,7 @@ void RPCConsole::setClientModel(ClientModel *model, int bestblock_height, int64_
connect(disconnectAction, &QAction::triggered, this, &RPCConsole::disconnectSelectedNode);
// peer table signal handling - update peer details when selecting new node
- connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::peerSelected);
+ connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::updateDetailWidget);
// peer table signal handling - update peer details when new nodes are added to the model
connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged, this, &RPCConsole::peerLayoutChanged);
// peer table signal handling - cache selected node ids
@@ -1021,18 +1016,6 @@ void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut));
}
-void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
-{
- Q_UNUSED(deselected);
-
- if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty())
- return;
-
- const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row());
- if (stats)
- updateNodeDetail(stats);
-}
-
void RPCConsole::peerLayoutAboutToChange()
{
QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes();
@@ -1049,7 +1032,6 @@ void RPCConsole::peerLayoutChanged()
if (!clientModel || !clientModel->getPeerTableModel())
return;
- const CNodeCombinedStats *stats = nullptr;
bool fUnselect = false;
bool fReselect = false;
@@ -1080,9 +1062,6 @@ void RPCConsole::peerLayoutChanged()
fUnselect = true;
fReselect = true;
}
-
- // get fresh stats on the detail node.
- stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
}
if (fUnselect && selectedRow >= 0) {
@@ -1097,12 +1076,20 @@ void RPCConsole::peerLayoutChanged()
}
}
- if (stats)
- updateNodeDetail(stats);
+ updateDetailWidget();
}
-void RPCConsole::updateNodeDetail(const CNodeCombinedStats *stats)
+void RPCConsole::updateDetailWidget()
{
+ QModelIndexList selected_rows;
+ auto selection_model = ui->peerWidget->selectionModel();
+ if (selection_model) selected_rows = selection_model->selectedRows();
+ if (!clientModel || !clientModel->getPeerTableModel() || selected_rows.size() != 1) {
+ ui->detailWidget->hide();
+ ui->peerHeading->setText(tr("Select a peer to view detailed information."));
+ return;
+ }
+ const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected_rows.first().row());
// update the detail ui with latest node information
QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " ");
peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid));
@@ -1260,8 +1247,7 @@ void RPCConsole::clearSelectedNode()
{
ui->peerWidget->selectionModel()->clearSelection();
cachedNodeids.clear();
- ui->detailWidget->hide();
- ui->peerHeading->setText(tr("Select a peer to view detailed information."));
+ updateDetailWidget();
}
void RPCConsole::showOrHideBanTableIfRequired()
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 280c5bd71a..8fea08ab5c 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -28,6 +28,7 @@ namespace Ui {
}
QT_BEGIN_NAMESPACE
+class QDateTime;
class QMenu;
class QItemSelection;
QT_END_NAMESPACE
@@ -94,6 +95,8 @@ private Q_SLOTS:
void showOrHideBanTableIfRequired();
/** clear the selected node */
void clearSelectedNode();
+ /** show detailed information on ui about selected node */
+ void updateDetailWidget();
public Q_SLOTS:
void clear(bool clearHistory = true);
@@ -115,8 +118,6 @@ public Q_SLOTS:
void browseHistory(int offset);
/** Scroll console view to end */
void scrollToEnd();
- /** Handle selection of peer in peers list */
- void peerSelected(const QItemSelection &selected, const QItemSelection &deselected);
/** Handle selection caching before update */
void peerLayoutAboutToChange();
/** Handle updated peer information */
@@ -137,8 +138,6 @@ Q_SIGNALS:
private:
void startExecutor();
void setTrafficGraphRange(int mins);
- /** show detailed information on ui about selected node */
- void updateNodeDetail(const CNodeCombinedStats *stats);
enum ColumnWidths
{
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 97fb88d71c..e765e643a3 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -28,12 +28,14 @@
#include <wallet/fees.h>
#include <wallet/wallet.h>
+#include <validation.h>
+
#include <QFontMetrics>
#include <QScrollBar>
#include <QSettings>
#include <QTextDocument>
-static const std::array<int, 9> confTargets = { {2, 4, 6, 12, 24, 48, 144, 504, 1008} };
+static constexpr std::array confTargets{2, 4, 6, 12, 24, 48, 144, 504, 1008};
int getConfTargetForIndex(int index) {
if (index+1 > static_cast<int>(confTargets.size())) {
return confTargets.back();
@@ -134,7 +136,7 @@ void SendCoinsDialog::setClientModel(ClientModel *_clientModel)
this->clientModel = _clientModel;
if (_clientModel) {
- connect(_clientModel, &ClientModel::numBlocksChanged, this, &SendCoinsDialog::updateSmartFeeLabel);
+ connect(_clientModel, &ClientModel::numBlocksChanged, this, &SendCoinsDialog::updateNumberOfBlocks);
}
}
@@ -171,8 +173,15 @@ void SendCoinsDialog::setModel(WalletModel *_model)
}
connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::updateSmartFeeLabel);
connect(ui->confTargetSelector, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::coinControlUpdateLabels);
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::updateFeeSectionControls);
+ connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::coinControlUpdateLabels);
+#else
connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::updateFeeSectionControls);
connect(ui->groupFee, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::coinControlUpdateLabels);
+#endif
+
connect(ui->customFee, &BitcoinAmountField::valueChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::updateSmartFeeLabel);
connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
@@ -744,6 +753,12 @@ void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl)
ctrl.fAllowWatchOnly = model->wallet().privateKeysDisabled();
}
+void SendCoinsDialog::updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state) {
+ if (sync_state == SynchronizationState::POST_INIT) {
+ updateSmartFeeLabel();
+ }
+}
+
void SendCoinsDialog::updateSmartFeeLabel()
{
if(!model || !model->getOptionsModel())
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index 6961aa7821..8519f1f65b 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -17,6 +17,7 @@ class ClientModel;
class PlatformStyle;
class SendCoinsEntry;
class SendCoinsRecipient;
+enum class SynchronizationState;
namespace Ui {
class SendCoinsDialog;
@@ -98,6 +99,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 updateSmartFeeLabel();
Q_SIGNALS:
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index f00f086d1e..5796a6ef56 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -25,8 +25,8 @@
#include <QScreen>
-SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) :
- QWidget(nullptr, f), curAlignment(0)
+SplashScreen::SplashScreen(const NetworkStyle* networkStyle)
+ : QWidget(), curAlignment(0)
{
// set reference point, paddings
int paddingRight = 50;
diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h
index a0cd677d3d..d49fd87055 100644
--- a/src/qt/splashscreen.h
+++ b/src/qt/splashscreen.h
@@ -28,7 +28,7 @@ class SplashScreen : public QWidget
Q_OBJECT
public:
- explicit SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle);
+ explicit SplashScreen(const NetworkStyle *networkStyle);
~SplashScreen();
void setNode(interfaces::Node& node);
diff --git a/src/qt/test/addressbooktests.h b/src/qt/test/addressbooktests.h
index 5de89c7592..e6d24f202f 100644
--- a/src/qt/test/addressbooktests.h
+++ b/src/qt/test/addressbooktests.h
@@ -15,7 +15,7 @@ class Node;
class AddressBookTests : public QObject
{
public:
- AddressBookTests(interfaces::Node& node) : m_node(node) {}
+ explicit AddressBookTests(interfaces::Node& node) : m_node(node) {}
interfaces::Node& m_node;
Q_OBJECT
diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp
index de1fbcb94c..a5c9138798 100644
--- a/src/qt/test/rpcnestedtests.cpp
+++ b/src/qt/test/rpcnestedtests.cpp
@@ -14,17 +14,26 @@
#include <QDir>
#include <QtGlobal>
-static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request)
+static RPCHelpMan rpcNestedTest_rpc()
{
- if (request.fHelp) {
- return "help message";
- }
- return request.params.write(0, 0);
+ return RPCHelpMan{
+ "rpcNestedTest",
+ "echo the passed string(s)",
+ {
+ {"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
+ {"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
+ {"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
+ },
+ {},
+ RPCExamples{""},
+ [](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
+ return request.params.write(0, 0);
+ },
+ };
}
-static const CRPCCommand vRPCCommands[] =
-{
- { "test", "rpcNestedTest", &rpcNestedTest_rpc, {} },
+static const CRPCCommand vRPCCommands[] = {
+ {"test", "rpcNestedTest", &rpcNestedTest_rpc, {"arg1", "arg2", "arg3"}},
};
void RPCNestedTests::rpcNestedTests()
@@ -34,41 +43,41 @@ void RPCNestedTests::rpcNestedTests()
tableRPC.appendCommand("rpcNestedTest", &vRPCCommands[0]);
TestingSetup test;
+ m_node.setContext(&test.m_node);
if (RPCIsInWarmup(nullptr)) SetRPCWarmupFinished();
std::string result;
std::string result2;
std::string filtered;
- interfaces::Node* node = &m_node;
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[chain]", &filtered); //simple result filtering with path
QVERIFY(result=="main");
QVERIFY(filtered == "getblockchaininfo()[chain]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getblock(getbestblockhash())[hash], true)");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())"); //simple 2 level nesting
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getblock(getbestblockhash())[hash], true)");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock( getblock( getblock(getbestblockhash())[hash] )[hash], true)"); //4 level nesting with whitespace, filtering path and boolean parameter
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo");
QVERIFY(result.substr(0,1) == "{");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()");
QVERIFY(result.substr(0,1) == "{");
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo "); //whitespace at the end will be tolerated
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo "); //whitespace at the end will be tolerated
QVERIFY(result.substr(0,1) == "{");
- (RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child containing the quotes in the key
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()[\"chain\"]")); //Quote path identifier are allowed, but look after a child containing the quotes in the key
QVERIFY(result == "null");
- (RPCConsole::RPCExecuteCommandLine(*node, result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed
- (RPCConsole::RPCExecuteCommandLine(*node, result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "createrawtransaction [] {} 0")); //parameter not in brackets are allowed
+ (RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction([],{},0)")); //parameter in brackets are allowed
QVERIFY(result == result2);
- (RPCConsole::RPCExecuteCommandLine(*node, result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parameters is allowed
+ (RPCConsole::RPCExecuteCommandLine(m_node, result2, "createrawtransaction( [], {} , 0 )")); //whitespace between parameters is allowed
QVERIFY(result == result2);
- RPCConsole::RPCExecuteCommandLine(*node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "getblock(getbestblockhash())[tx][0]", &filtered);
QVERIFY(result == "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
QVERIFY(filtered == "getblock(getbestblockhash())[tx][0]");
@@ -93,35 +102,35 @@ void RPCNestedTests::rpcNestedTests()
RPCConsole::RPCParseCommandLine(nullptr, result, "help(importprivkey(abc), walletpassphrase(def))", false, &filtered);
QVERIFY(filtered == "help(importprivkey(…), walletpassphrase(…))");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest");
QVERIFY(result == "[]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest ''");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest ''");
QVERIFY(result == "[\"\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest \"\"");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest \"\"");
QVERIFY(result == "[\"\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest '' abc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest '' abc");
QVERIFY(result == "[\"\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc '' abc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc '' abc");
QVERIFY(result == "[\"abc\",\"\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc abc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc abc");
QVERIFY(result == "[\"abc\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc\t\tabc");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc\t\tabc");
QVERIFY(result == "[\"abc\",\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc )");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc )");
QVERIFY(result == "[\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc )");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest( abc )");
QVERIFY(result == "[\"abc\"]");
- RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest( abc , cba )");
+ RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest( abc , cba )");
QVERIFY(result == "[\"abc\",\"cba\"]");
// do the QVERIFY_EXCEPTION_THROWN checks only with Qt5.3 and higher (QVERIFY_EXCEPTION_THROWN was introduced in Qt5.3)
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
- (RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments
- (RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo()()()")); //tolerate non command brackts
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "getblockchaininfo(True)"), UniValue); //invalid argument
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "a(getblockchaininfo(True))"), UniValue); //method not found
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using ,
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
- QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(*node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() .\n"), std::runtime_error); //invalid syntax
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo() getblockchaininfo()"), std::runtime_error); //invalid syntax
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo(")); //tolerate non closing brackets if we have no arguments
+ (RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo()()()")); //tolerate non command brackts
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "getblockchaininfo(True)"), UniValue); //invalid argument
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "a(getblockchaininfo(True))"), UniValue); //method not found
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest abc,,abc"), std::runtime_error); //don't tollerate empty arguments when using ,
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,abc)"), std::runtime_error); //don't tollerate empty arguments when using ,
+ QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(m_node, result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using ,
}
diff --git a/src/qt/test/rpcnestedtests.h b/src/qt/test/rpcnestedtests.h
index 0a00d1113a..320275129d 100644
--- a/src/qt/test/rpcnestedtests.h
+++ b/src/qt/test/rpcnestedtests.h
@@ -15,7 +15,7 @@ class Node;
class RPCNestedTests : public QObject
{
public:
- RPCNestedTests(interfaces::Node& node) : m_node(node) {}
+ explicit RPCNestedTests(interfaces::Node& node) : m_node(node) {}
interfaces::Node& m_node;
Q_OBJECT
diff --git a/src/qt/test/wallettests.h b/src/qt/test/wallettests.h
index 8ee40bf07f..dfca3370f7 100644
--- a/src/qt/test/wallettests.h
+++ b/src/qt/test/wallettests.h
@@ -15,7 +15,7 @@ class Node;
class WalletTests : public QObject
{
public:
- WalletTests(interfaces::Node& node) : m_node(node) {}
+ explicit WalletTests(interfaces::Node& node) : m_node(node) {}
interfaces::Node& m_node;
Q_OBJECT
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index c560dc58e7..3148089b52 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -54,6 +54,30 @@ struct TxLessThan
}
};
+// queue notifications to show a non freezing progress dialog e.g. for rescan
+struct TransactionNotification
+{
+public:
+ TransactionNotification() {}
+ TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
+ hash(_hash), status(_status), showTransaction(_showTransaction) {}
+
+ void invoke(QObject *ttm)
+ {
+ QString strHash = QString::fromStdString(hash.GetHex());
+ qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
+ bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
+ Q_ARG(QString, strHash),
+ Q_ARG(int, status),
+ Q_ARG(bool, showTransaction));
+ assert(invoked);
+ }
+private:
+ uint256 hash;
+ ChangeType status;
+ bool showTransaction;
+};
+
// Private implementation
class TransactionTablePriv
{
@@ -71,6 +95,12 @@ public:
*/
QList<TransactionRecord> cachedWallet;
+ bool fQueueNotifications = false;
+ std::vector< TransactionNotification > vQueueNotifications;
+
+ void NotifyTransactionChanged(const uint256 &hash, ChangeType status);
+ void ShowProgress(const std::string &title, int nProgress);
+
/* Query entire wallet anew from core.
*/
void refreshWallet(interfaces::Wallet& wallet)
@@ -674,34 +704,7 @@ void TransactionTableModel::updateDisplayUnit()
Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));
}
-// queue notifications to show a non freezing progress dialog e.g. for rescan
-struct TransactionNotification
-{
-public:
- TransactionNotification() {}
- TransactionNotification(uint256 _hash, ChangeType _status, bool _showTransaction):
- hash(_hash), status(_status), showTransaction(_showTransaction) {}
-
- void invoke(QObject *ttm)
- {
- QString strHash = QString::fromStdString(hash.GetHex());
- qDebug() << "NotifyTransactionChanged: " + strHash + " status= " + QString::number(status);
- bool invoked = QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection,
- Q_ARG(QString, strHash),
- Q_ARG(int, status),
- Q_ARG(bool, showTransaction));
- assert(invoked);
- }
-private:
- uint256 hash;
- ChangeType status;
- bool showTransaction;
-};
-
-static bool fQueueNotifications = false;
-static std::vector< TransactionNotification > vQueueNotifications;
-
-static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 &hash, ChangeType status)
+void TransactionTablePriv::NotifyTransactionChanged(const uint256 &hash, ChangeType status)
{
// Find transaction in wallet
// Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)
@@ -714,10 +717,10 @@ static void NotifyTransactionChanged(TransactionTableModel *ttm, const uint256 &
vQueueNotifications.push_back(notification);
return;
}
- notification.invoke(ttm);
+ notification.invoke(parent);
}
-static void ShowProgress(TransactionTableModel *ttm, const std::string &title, int nProgress)
+void TransactionTablePriv::ShowProgress(const std::string &title, int nProgress)
{
if (nProgress == 0)
fQueueNotifications = true;
@@ -726,27 +729,27 @@ static void ShowProgress(TransactionTableModel *ttm, const std::string &title, i
{
fQueueNotifications = false;
if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons
- bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
+ bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
assert(invoked);
}
for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
{
if (vQueueNotifications.size() - i <= 10) {
- bool invoked = QMetaObject::invokeMethod(ttm, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
+ bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
assert(invoked);
}
- vQueueNotifications[i].invoke(ttm);
+ vQueueNotifications[i].invoke(parent);
}
- std::vector<TransactionNotification >().swap(vQueueNotifications); // clear
+ vQueueNotifications.clear();
}
}
void TransactionTableModel::subscribeToCoreSignals()
{
// Connect signals to wallet
- m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2));
- m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2));
+ m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged(std::bind(&TransactionTablePriv::NotifyTransactionChanged, priv, std::placeholders::_1, std::placeholders::_2));
+ m_handler_show_progress = walletModel->wallet().handleShowProgress(std::bind(&TransactionTablePriv::ShowProgress, priv, std::placeholders::_1, std::placeholders::_2));
}
void TransactionTableModel::unsubscribeFromCoreSignals()
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 54ecfc38ec..e14e22e9de 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -237,7 +237,7 @@ void TransactionView::setModel(WalletModel *_model)
if (_model->getOptionsModel())
{
// Add third party transaction URLs to context menu
- QStringList listUrls = _model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts);
+ QStringList listUrls = GUIUtil::SplitSkipEmptyParts(_model->getOptionsModel()->getThirdPartyTxUrls(), "|");
for (int i = 0; i < listUrls.size(); ++i)
{
QString url = listUrls[i].trimmed();
@@ -275,30 +275,30 @@ void TransactionView::chooseDate(int idx)
break;
case Today:
transactionProxyModel->setDateRange(
- QDateTime(current),
+ GUIUtil::StartOfDay(current),
TransactionFilterProxy::MAX_DATE);
break;
case ThisWeek: {
// Find last Monday
QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
transactionProxyModel->setDateRange(
- QDateTime(startOfWeek),
+ GUIUtil::StartOfDay(startOfWeek),
TransactionFilterProxy::MAX_DATE);
} break;
case ThisMonth:
transactionProxyModel->setDateRange(
- QDateTime(QDate(current.year(), current.month(), 1)),
+ GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1)),
TransactionFilterProxy::MAX_DATE);
break;
case LastMonth:
transactionProxyModel->setDateRange(
- QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)),
- QDateTime(QDate(current.year(), current.month(), 1)));
+ GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1).addMonths(-1)),
+ GUIUtil::StartOfDay(QDate(current.year(), current.month(), 1)));
break;
case ThisYear:
transactionProxyModel->setDateRange(
- QDateTime(QDate(current.year(), 1, 1)),
+ GUIUtil::StartOfDay(QDate(current.year(), 1, 1)),
TransactionFilterProxy::MAX_DATE);
break;
case Range:
@@ -583,8 +583,8 @@ void TransactionView::dateRangeChanged()
if(!transactionProxyModel)
return;
transactionProxyModel->setDateRange(
- QDateTime(dateFrom->date()),
- QDateTime(dateTo->date()).addDays(1));
+ GUIUtil::StartOfDay(dateFrom->date()),
+ GUIUtil::StartOfDay(dateTo->date()).addDays(1));
}
void TransactionView::focusTransaction(const QModelIndex &idx)
diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp
index d9e0274d01..83f3cccbff 100644
--- a/src/qt/walletcontroller.cpp
+++ b/src/qt/walletcontroller.cpp
@@ -128,10 +128,20 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal
}
// Instantiate model and register it.
- WalletModel* wallet_model = new WalletModel(std::move(wallet), m_client_model, m_platform_style, nullptr);
- // Handler callback runs in a different thread so fix wallet model thread affinity.
+ WalletModel* wallet_model = new WalletModel(std::move(wallet), m_client_model, m_platform_style,
+ nullptr /* required for the following moveToThread() call */);
+
+ // Move WalletModel object to the thread that created the WalletController
+ // object (GUI main thread), instead of the current thread, which could be
+ // an outside wallet thread or RPC thread sending a LoadWallet notification.
+ // This ensures queued signals sent to the WalletModel object will be
+ // handled on the GUI event loop.
wallet_model->moveToThread(thread());
- wallet_model->setParent(this);
+ // setParent(parent) must be called in the thread which created the parent object. More details in #18948.
+ GUIUtil::ObjectInvoke(this, [wallet_model, this] {
+ wallet_model->setParent(this);
+ }, GUIUtil::blockingGUIThreadConnection());
+
m_wallets.push_back(wallet_model);
// WalletModel::startPollBalance needs to be called in a thread managed by
@@ -157,7 +167,6 @@ WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wal
// Re-emit coinsSent signal from wallet model.
connect(wallet_model, &WalletModel::coinsSent, this, &WalletController::coinsSent);
- // Notify walletAdded signal on the GUI thread.
Q_EMIT walletAdded(wallet_model);
return wallet_model;
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index f16761d6b2..2edb7eff8a 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.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 <qt/createwalletdialog.h>
-#include <qt/walletcontroller.h>
#include <qt/walletframe.h>
-#include <qt/walletmodel.h>
#include <qt/bitcoingui.h>
+#include <qt/createwalletdialog.h>
+#include <qt/overviewpage.h>
+#include <qt/walletcontroller.h>
+#include <qt/walletmodel.h>
#include <qt/walletview.h>
#include <cassert>
@@ -18,10 +19,11 @@
#include <QPushButton>
#include <QVBoxLayout>
-WalletFrame::WalletFrame(const PlatformStyle *_platformStyle, BitcoinGUI *_gui) :
- QFrame(_gui),
- gui(_gui),
- platformStyle(_platformStyle)
+WalletFrame::WalletFrame(const PlatformStyle* _platformStyle, BitcoinGUI* _gui)
+ : QFrame(_gui),
+ gui(_gui),
+ platformStyle(_platformStyle),
+ m_size_hint(OverviewPage{platformStyle, nullptr}.sizeHint())
{
// Leave HBox hook for adding a list view later
QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
@@ -194,11 +196,11 @@ void WalletFrame::gotoLoadPSBT(bool from_clipboard)
}
}
-void WalletFrame::encryptWallet(bool status)
+void WalletFrame::encryptWallet()
{
WalletView *walletView = currentWalletView();
if (walletView)
- walletView->encryptWallet(status);
+ walletView->encryptWallet();
}
void WalletFrame::backupWallet()
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index 2b5f263468..271ddfc6c2 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -45,6 +45,8 @@ public:
void showOutOfSyncWarning(bool fShow);
+ QSize sizeHint() const override { return m_size_hint; }
+
Q_SIGNALS:
/** Notify that the user has requested more information about the out-of-sync warning */
void requestedSyncWarningInfo();
@@ -59,6 +61,8 @@ private:
const PlatformStyle *platformStyle;
+ const QSize m_size_hint;
+
public:
WalletView* currentWalletView() const;
WalletModel* currentWalletModel() const;
@@ -82,7 +86,7 @@ public Q_SLOTS:
void gotoLoadPSBT(bool from_clipboard = false);
/** Encrypt the wallet */
- void encryptWallet(bool status);
+ void encryptWallet();
/** Backup the wallet */
void backupWallet();
/** Change encrypted wallet passphrase */
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 6a3f903206..cad472b43b 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -313,12 +313,9 @@ WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
}
}
-bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase)
+bool WalletModel::setWalletEncrypted(const SecureString& passphrase)
{
- if (encrypted) {
- return m_wallet->encryptWallet(passphrase);
- }
- return false;
+ return m_wallet->encryptWallet(passphrase);
}
bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index fd52db2da3..9a3c3f2f66 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -105,7 +105,7 @@ public:
SendCoinsReturn sendCoins(WalletModelTransaction &transaction);
// Wallet encryption
- bool setWalletEncrypted(bool encrypted, const SecureString &passphrase);
+ bool setWalletEncrypted(const SecureString& passphrase);
// Passphrase only needed when unlocking
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString());
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 2fc883a5f5..b1e6b43e60 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -258,11 +258,11 @@ void WalletView::updateEncryptionStatus()
Q_EMIT encryptionStatusChanged();
}
-void WalletView::encryptWallet(bool status)
+void WalletView::encryptWallet()
{
if(!walletModel)
return;
- AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt : AskPassphraseDialog::Decrypt, this);
+ AskPassphraseDialog dlg(AskPassphraseDialog::Encrypt, this);
dlg.setModel(walletModel);
dlg.exec();
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index f186554758..68f8a5e95b 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -92,7 +92,7 @@ public Q_SLOTS:
*/
void processNewTransaction(const QModelIndex& parent, int start, int /*end*/);
/** Encrypt the wallet */
- void encryptWallet(bool status);
+ void encryptWallet();
/** Backup the wallet */
void backupWallet();
/** Change encrypted wallet passphrase */
diff --git a/src/randomenv.cpp b/src/randomenv.cpp
index 073d82b491..9248db1539 100644
--- a/src/randomenv.cpp
+++ b/src/randomenv.cpp
@@ -53,7 +53,7 @@
#include <sys/vmmeter.h>
#endif
#endif
-#ifdef __linux__
+#if defined(HAVE_STRONG_GETAUXVAL) || defined(HAVE_WEAK_GETAUXVAL)
#include <sys/auxv.h>
#endif
@@ -67,8 +67,9 @@ void RandAddSeedPerfmon(CSHA512& hasher)
#ifdef WIN32
// Seed with the entire set of perfmon data
- // This can take up to 2 seconds, so only do it every 10 minutes
- static std::atomic<std::chrono::seconds> last_perfmon{std::chrono::seconds{0}};
+ // This can take up to 2 seconds, so only do it every 10 minutes.
+ // Initialize last_perfmon to 0 seconds, we don't skip the first call.
+ static std::atomic<std::chrono::seconds> last_perfmon{0s};
auto last_time = last_perfmon.load();
auto current_time = GetTime<std::chrono::seconds>();
if (current_time < last_time + std::chrono::minutes{10}) return;
@@ -83,7 +84,7 @@ void RandAddSeedPerfmon(CSHA512& hasher)
ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, vData.data(), &nSize);
if (ret != ERROR_MORE_DATA || vData.size() >= nMaxSize)
break;
- vData.resize(std::max((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
+ vData.resize(std::min((vData.size() * 3) / 2, nMaxSize)); // Grow size of buffer exponentially
}
RegCloseKey(HKEY_PERFORMANCE_DATA);
if (ret == ERROR_SUCCESS) {
@@ -325,7 +326,7 @@ void RandAddStaticEnv(CSHA512& hasher)
// Bitcoin client version
hasher << CLIENT_VERSION;
-#ifdef __linux__
+#if defined(HAVE_STRONG_GETAUXVAL) || defined(HAVE_WEAK_GETAUXVAL)
// Information available through getauxval()
# ifdef AT_HWCAP
hasher << getauxval(AT_HWCAP);
@@ -345,7 +346,7 @@ void RandAddStaticEnv(CSHA512& hasher)
const char* exec_str = (const char*)getauxval(AT_EXECFN);
if (exec_str) hasher.Write((const unsigned char*)exec_str, strlen(exec_str) + 1);
# endif
-#endif // __linux__
+#endif // HAVE_STRONG_GETAUXVAL || HAVE_WEAK_GETAUXVAL
#ifdef HAVE_GETCPUID
AddAllCPUID(hasher);
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index a162c1ee70..57327e6004 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -17,6 +17,7 @@
#include <node/coinstats.h>
#include <node/context.h>
#include <node/utxo_snapshot.h>
+#include <policy/fees.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -81,6 +82,15 @@ ChainstateManager& EnsureChainman(const util::Ref& context)
return *node.chainman;
}
+CBlockPolicyEstimator& EnsureFeeEstimator(const util::Ref& context)
+{
+ NodeContext& node = EnsureNodeContext(context);
+ if (!node.fee_estimator) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
+ }
+ return *node.fee_estimator;
+}
+
/* Calculate the difficulty for a given block index.
*/
double GetDifficulty(const CBlockIndex* blockindex)
@@ -1816,12 +1826,12 @@ static RPCHelpMan getblockstats()
{RPCResult::Type::NUM, "outs", "The number of outputs"},
{RPCResult::Type::NUM, "subsidy", "The block subsidy"},
{RPCResult::Type::NUM, "swtotal_size", "Total size of all segwit transactions"},
- {RPCResult::Type::NUM, "swtotal_weight", "Total weight of all segwit transactions divided by segwit scale factor (4)"},
+ {RPCResult::Type::NUM, "swtotal_weight", "Total weight of all segwit transactions"},
{RPCResult::Type::NUM, "swtxs", "The number of segwit transactions"},
{RPCResult::Type::NUM, "time", "The block time"},
{RPCResult::Type::NUM, "total_out", "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"},
{RPCResult::Type::NUM, "total_size", "Total size of all non-coinbase transactions"},
- {RPCResult::Type::NUM, "total_weight", "Total weight of all non-coinbase transactions divided by segwit scale factor (4)"},
+ {RPCResult::Type::NUM, "total_weight", "Total weight of all non-coinbase transactions"},
{RPCResult::Type::NUM, "totalfee", "The fee total"},
{RPCResult::Type::NUM, "txs", "The number of transactions (including coinbase)"},
{RPCResult::Type::NUM, "utxo_increase", "The increase/decrease in the number of unspent outputs"},
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index 5b362bf211..91766aacc9 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -15,6 +15,7 @@ extern RecursiveMutex cs_main;
class CBlock;
class CBlockIndex;
+class CBlockPolicyEstimator;
class CTxMemPool;
class ChainstateManager;
class UniValue;
@@ -54,5 +55,6 @@ void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES],
NodeContext& EnsureNodeContext(const util::Ref& context);
CTxMemPool& EnsureMemPool(const util::Ref& context);
ChainstateManager& EnsureChainman(const util::Ref& context);
+CBlockPolicyEstimator& EnsureFeeEstimator(const util::Ref& context);
#endif
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 88c8ebe1f6..042005b9a6 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -41,7 +41,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendtoaddress", 5 , "replaceable" },
{ "sendtoaddress", 6 , "conf_target" },
{ "sendtoaddress", 8, "avoid_reuse" },
- { "sendtoaddress", 9, "verbose"},
+ { "sendtoaddress", 9, "fee_rate"},
+ { "sendtoaddress", 10, "verbose"},
{ "settxfee", 0, "amount" },
{ "sethdseed", 0, "newkeypool" },
{ "getreceivedbyaddress", 1, "minconf" },
@@ -73,7 +74,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendmany", 4, "subtractfeefrom" },
{ "sendmany", 5 , "replaceable" },
{ "sendmany", 6 , "conf_target" },
- { "sendmany", 8, "verbose" },
+ { "sendmany", 8, "fee_rate"},
+ { "sendmany", 9, "verbose" },
{ "deriveaddresses", 1, "range" },
{ "scantxoutset", 1, "scanobjects" },
{ "addmultisigaddress", 0, "nrequired" },
@@ -129,7 +131,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "lockunspent", 1, "transactions" },
{ "send", 0, "outputs" },
{ "send", 1, "conf_target" },
- { "send", 3, "options" },
+ { "send", 3, "fee_rate"},
+ { "send", 4, "options" },
{ "importprivkey", 2, "rescan" },
{ "importaddress", 2, "rescan" },
{ "importaddress", 3, "p2sh" },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index b04e106b2d..965b278bfa 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -242,12 +242,7 @@ static RPCHelpMan generatetodescriptor()
static RPCHelpMan generate()
{
return RPCHelpMan{"generate", "has been replaced by the -generate cli option. Refer to -help for more information.", {}, {}, RPCExamples{""}, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
-
- if (request.fHelp) {
- throw std::runtime_error(self.ToString());
- } else {
throw JSONRPCError(RPC_METHOD_NOT_FOUND, self.ToString());
- }
}};
}
@@ -352,7 +347,7 @@ static RPCHelpMan generateblock()
txs.push_back(MakeTransactionRef(std::move(mtx)));
} else {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("Transaction decode failed for %s", str));
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("Transaction decode failed for %s. Make sure the tx has at least one input.", str));
}
}
@@ -1027,21 +1022,19 @@ static RPCHelpMan submitheader()
static RPCHelpMan estimatesmartfee()
{
return RPCHelpMan{"estimatesmartfee",
- "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
- "confirmation within conf_target blocks if possible and return the number of blocks\n"
- "for which the estimate is valid. Uses virtual transaction size as defined\n"
- "in BIP 141 (witness data is discounted).\n",
- {
- {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
- {"estimate_mode", RPCArg::Type::STR, /* default */ "CONSERVATIVE", "The fee estimate mode.\n"
+ "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
+ "confirmation within conf_target blocks if possible and return the number of blocks\n"
+ "for which the estimate is valid. Uses virtual transaction size as defined\n"
+ "in BIP 141 (witness data is discounted).\n",
+ {
+ {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"},
+ {"estimate_mode", RPCArg::Type::STR, /* default */ "conservative", "The fee estimate mode.\n"
" Whether to return a more conservative estimate which also satisfies\n"
" a longer history. A conservative estimate potentially returns a\n"
" higher feerate and is more likely to be sufficient for the desired\n"
" target, but is not as responsive to short term drops in the\n"
- " prevailing fee market. Must be one of:\n"
- " \"UNSET\"\n"
- " \"ECONOMICAL\"\n"
- " \"CONSERVATIVE\""},
+ " prevailing fee market. Must be one of (case insensitive):\n"
+ "\"" + FeeModes("\"\n\"") + "\""},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@@ -1064,13 +1057,16 @@ static RPCHelpMan estimatesmartfee()
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR});
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
- unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+
+ CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
+
+ unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
bool conservative = true;
if (!request.params[1].isNull()) {
FeeEstimateMode fee_mode;
if (!FeeModeFromString(request.params[1].get_str(), fee_mode)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
+ throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage());
}
if (fee_mode == FeeEstimateMode::ECONOMICAL) conservative = false;
}
@@ -1078,7 +1074,7 @@ static RPCHelpMan estimatesmartfee()
UniValue result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
FeeCalculation feeCalc;
- CFeeRate feeRate = ::feeEstimator.estimateSmartFee(conf_target, &feeCalc, conservative);
+ CFeeRate feeRate = fee_estimator.estimateSmartFee(conf_target, &feeCalc, conservative);
if (feeRate != CFeeRate(0)) {
result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK()));
} else {
@@ -1149,7 +1145,10 @@ static RPCHelpMan estimaterawfee()
{
RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true);
RPCTypeCheckArgument(request.params[0], UniValue::VNUM);
- unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+
+ CBlockPolicyEstimator& fee_estimator = EnsureFeeEstimator(request.context);
+
+ unsigned int max_target = fee_estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
unsigned int conf_target = ParseConfirmTarget(request.params[0], max_target);
double threshold = 0.95;
if (!request.params[1].isNull()) {
@@ -1166,9 +1165,9 @@ static RPCHelpMan estimaterawfee()
EstimationResult buckets;
// Only output results for horizons which track the target
- if (conf_target > ::feeEstimator.HighestTargetTracked(horizon)) continue;
+ if (conf_target > fee_estimator.HighestTargetTracked(horizon)) continue;
- feeRate = ::feeEstimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
+ feeRate = fee_estimator.estimateRawFee(conf_target, threshold, horizon, &buckets);
UniValue horizon_result(UniValue::VOBJ);
UniValue errors(UniValue::VARR);
UniValue passbucket(UniValue::VOBJ);
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 0c982317f5..b3102a236d 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -624,8 +624,6 @@ static RPCHelpMan echo(const std::string& name)
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
- if (request.fHelp) throw std::runtime_error(self.ToString());
-
if (request.params[9].isStr()) {
CHECK_NONFATAL(request.params[9].get_str() != "trigger_internal_bug");
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index def21b119e..6a2d1ea77f 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -29,6 +29,15 @@
#include <univalue.h>
+const std::vector<std::string> CONNECTION_TYPE_DOC{
+ "outbound-full-relay (default automatic connections)",
+ "block-relay-only (does not relay transactions or addresses)",
+ "inbound (initiated by the peer)",
+ "manual (added via addnode RPC or -addnode/-connect configuration options)",
+ "addr-fetch (short-lived automatic connection for soliciting addresses)",
+ "feeler (short-lived automatic connection for testing addresses)"
+};
+
static RPCHelpMan getconnectioncount()
{
return RPCHelpMan{"getconnectioncount",
@@ -94,6 +103,7 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"},
{RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"},
{RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"},
+ {RPCResult::Type::STR, "network", "Network (ipv4, ipv6, or onion) the peer connected through"},
{RPCResult::Type::NUM, "mapped_as", "The AS in the BGP route to the peer used for diversifying\n"
"peer selection (only available if the asmap config flag is set)"},
{RPCResult::Type::STR_HEX, "services", "The services offered"},
@@ -116,9 +126,13 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::NUM, "version", "The peer version, such as 70001"},
{RPCResult::Type::STR, "subver", "The string version"},
{RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"},
+ {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::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n"
"(DEPRECATED, returned only if the config option -deprecatedrpc=getpeerinfo_addnode is passed)"},
- {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + "."},
+ {RPCResult::Type::STR, "connection_type", "Type of connection: \n" + Join(CONNECTION_TYPE_DOC, ",\n") + ".\n"
+ "Please note this output is unlikely to be stable in upcoming releases as we iterate to\n"
+ "best capture connection behaviors."},
{RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"},
{RPCResult::Type::NUM, "banscore", "The ban score (DEPRECATED, returned only if config option -deprecatedrpc=banscore is passed)"},
{RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"},
@@ -127,7 +141,8 @@ static RPCHelpMan getpeerinfo()
{
{RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
}},
- {RPCResult::Type::BOOL, "whitelisted", "Whether the peer is whitelisted"},
+ {RPCResult::Type::BOOL, "whitelisted", /* optional */ true, "Whether the peer is whitelisted with default permissions\n"
+ "(DEPRECATED, returned only if config option -deprecatedrpc=whitelisted is passed)"},
{RPCResult::Type::NUM, "minfeefilter", "The minimum fee rate for transactions this peer accepts"},
{RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "",
{
@@ -139,7 +154,8 @@ static RPCHelpMan getpeerinfo()
{
{RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n"
"When a message type is not listed in this json object, the bytes received are 0.\n"
- "Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."}
+ "Only known message types can appear as keys in the object and all bytes received\n"
+ "of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."}
}},
}},
}},
@@ -151,8 +167,9 @@ static RPCHelpMan getpeerinfo()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
NodeContext& node = EnsureNodeContext(request.context);
- if(!node.connman)
+ if(!node.connman || !node.peerman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
+ }
std::vector<CNodeStats> vstats;
node.connman->GetNodeStats(vstats);
@@ -162,13 +179,16 @@ static RPCHelpMan getpeerinfo()
for (const CNodeStats& stats : vstats) {
UniValue obj(UniValue::VOBJ);
CNodeStateStats statestats;
- bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
+ bool fStateStats = node.peerman->GetNodeStateStats(stats.nodeid, statestats);
obj.pushKV("id", stats.nodeid);
obj.pushKV("addr", stats.addrName);
- if (!(stats.addrLocal.empty()))
- obj.pushKV("addrlocal", stats.addrLocal);
- if (stats.addrBind.IsValid())
+ if (stats.addrBind.IsValid()) {
obj.pushKV("addrbind", stats.addrBind.ToString());
+ }
+ if (!(stats.addrLocal.empty())) {
+ obj.pushKV("addrlocal", stats.addrLocal);
+ }
+ obj.pushKV("network", stats.m_network);
if (stats.m_mapped_as != 0) {
obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as));
}
@@ -198,6 +218,8 @@ static RPCHelpMan getpeerinfo()
// their ver message.
obj.pushKV("subver", stats.cleanSubVer);
obj.pushKV("inbound", stats.fInbound);
+ obj.pushKV("bip152_hb_to", stats.m_bip152_highbandwidth_to);
+ obj.pushKV("bip152_hb_from", stats.m_bip152_highbandwidth_from);
if (IsDeprecatedRPCEnabled("getpeerinfo_addnode")) {
// addnode is deprecated in v0.21 for removal in v0.22
obj.pushKV("addnode", stats.m_manual_connection);
@@ -216,7 +238,10 @@ static RPCHelpMan getpeerinfo()
}
obj.pushKV("inflight", heights);
}
- obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
+ if (IsDeprecatedRPCEnabled("whitelisted")) {
+ // whitelisted is deprecated in v0.21 for removal in v0.22
+ obj.pushKV("whitelisted", stats.m_legacyWhitelisted);
+ }
UniValue permissions(UniValue::VARR);
for (const auto& permission : NetPermissions::ToStrings(stats.m_permissionFlags)) {
permissions.push_back(permission);
@@ -268,10 +293,10 @@ static RPCHelpMan addnode()
std::string strCommand;
if (!request.params[1].isNull())
strCommand = request.params[1].get_str();
- if (request.fHelp || request.params.size() != 2 ||
- (strCommand != "onetry" && strCommand != "add" && strCommand != "remove"))
+ if (strCommand != "onetry" && strCommand != "add" && strCommand != "remove") {
throw std::runtime_error(
self.ToString());
+ }
NodeContext& node = EnsureNodeContext(request.context);
if(!node.connman)
@@ -462,12 +487,12 @@ static RPCHelpMan getnettotals()
obj.pushKV("timemillis", GetTimeMillis());
UniValue outboundLimit(UniValue::VOBJ);
- outboundLimit.pushKV("timeframe", node.connman->GetMaxOutboundTimeframe());
+ outboundLimit.pushKV("timeframe", count_seconds(node.connman->GetMaxOutboundTimeframe()));
outboundLimit.pushKV("target", node.connman->GetMaxOutboundTarget());
outboundLimit.pushKV("target_reached", node.connman->OutboundTargetReached(false));
outboundLimit.pushKV("serve_historical_blocks", !node.connman->OutboundTargetReached(true));
outboundLimit.pushKV("bytes_left_in_cycle", node.connman->GetOutboundTargetBytesLeft());
- outboundLimit.pushKV("time_left_in_cycle", node.connman->GetMaxOutboundTimeLeftInCycle());
+ outboundLimit.pushKV("time_left_in_cycle", count_seconds(node.connman->GetMaxOutboundTimeLeftInCycle()));
obj.pushKV("uploadtarget", outboundLimit);
return obj;
},
@@ -477,11 +502,9 @@ static RPCHelpMan getnettotals()
static UniValue GetNetworksInfo()
{
UniValue networks(UniValue::VARR);
- for(int n=0; n<NET_MAX; ++n)
- {
+ for (int n = 0; n < NET_MAX; ++n) {
enum Network network = static_cast<enum Network>(n);
- if(network == NET_UNROUTABLE || network == NET_INTERNAL)
- continue;
+ if (network == NET_UNROUTABLE || network == NET_I2P || network == NET_CJDNS || network == NET_INTERNAL) continue;
proxyType proxy;
UniValue obj(UniValue::VOBJ);
GetProxy(network, proxy);
@@ -559,7 +582,9 @@ static RPCHelpMan getnetworkinfo()
obj.pushKV("localservices", strprintf("%016x", services));
obj.pushKV("localservicesnames", GetServicesNames(services));
}
- obj.pushKV("localrelay", g_relay_txes);
+ if (node.peerman) {
+ obj.pushKV("localrelay", !node.peerman->IgnoresIncomingTxs());
+ }
obj.pushKV("timeoffset", GetTimeOffset());
if (node.connman) {
obj.pushKV("networkactive", node.connman->GetNetworkActive());
@@ -610,7 +635,7 @@ static RPCHelpMan setban()
std::string strCommand;
if (!request.params[1].isNull())
strCommand = request.params[1].get_str();
- if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
+ if (strCommand != "add" && strCommand != "remove") {
throw std::runtime_error(help.ToString());
}
NodeContext& node = EnsureNodeContext(request.context);
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 7a6b605ec3..f6ddaf379b 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -244,16 +244,15 @@ static RPCHelpMan gettxoutproof()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
std::set<uint256> setTxids;
- uint256 oneTxid;
UniValue txids = request.params[0].get_array();
+ if (txids.empty()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Parameter 'txids' cannot be empty");
+ }
for (unsigned int idx = 0; idx < txids.size(); idx++) {
- const UniValue& txid = txids[idx];
- uint256 hash(ParseHashV(txid, "txid"));
- if (setTxids.count(hash)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ") + txid.get_str());
+ auto ret = setTxids.insert(ParseHashV(txids[idx], "txid"));
+ if (!ret.second) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated txid: ") + txids[idx].get_str());
}
- setTxids.insert(hash);
- oneTxid = hash;
}
CBlockIndex* pblockindex = nullptr;
@@ -287,7 +286,7 @@ static RPCHelpMan gettxoutproof()
LOCK(cs_main);
if (pblockindex == nullptr) {
- const CTransactionRef tx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, oneTxid, Params().GetConsensus(), hashBlock);
+ const CTransactionRef tx = GetTransaction(/* block_index */ nullptr, /* mempool */ nullptr, *setTxids.begin(), Params().GetConsensus(), hashBlock);
if (!tx || hashBlock.IsNull()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
}
@@ -656,8 +655,8 @@ static RPCHelpMan combinerawtransaction()
std::vector<CMutableTransaction> txVariants(txs.size());
for (unsigned int idx = 0; idx < txs.size(); idx++) {
- if (!DecodeHexTx(txVariants[idx], txs[idx].get_str(), true)) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed for tx %d", idx));
+ if (!DecodeHexTx(txVariants[idx], txs[idx].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, strprintf("TX decode failed for tx %d. Make sure the tx has at least one input.", idx));
}
}
@@ -780,8 +779,8 @@ static RPCHelpMan signrawtransactionwithkey()
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true);
CMutableTransaction mtx;
- if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ if (!DecodeHexTx(mtx, request.params[0].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
}
FillableSigningProvider keystore;
@@ -847,10 +846,10 @@ static RPCHelpMan sendrawtransaction()
UniValueType(), // VNUM or VSTR, checked inside AmountFromValue()
});
- // parse hex string from parameter
CMutableTransaction mtx;
- if (!DecodeHexTx(mtx, request.params[0].get_str()))
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ if (!DecodeHexTx(mtx, request.params[0].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
+ }
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
const CFeeRate max_raw_tx_fee_rate = request.params[1].isNull() ?
@@ -928,7 +927,7 @@ static RPCHelpMan testmempoolaccept()
CMutableTransaction mtx;
if (!DecodeHexTx(mtx, request.params[0].get_array()[0].get_str())) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
}
CTransactionRef tx(MakeTransactionRef(std::move(mtx)));
const uint256& tx_hash = tx->GetHash();
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index f004ecc20c..122a92f084 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -286,7 +286,7 @@ void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
SignTransactionResultToJSON(mtx, complete, coins, input_errors, result);
}
-void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, std::map<int, std::string>& input_errors, UniValue& result)
+void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, std::string>& input_errors, UniValue& result)
{
// Make errors UniValue
UniValue vErrors(UniValue::VARR);
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index 942314eccf..ce7d5834fa 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -25,7 +25,7 @@ class SigningProvider;
* @param result JSON object where signed transaction results accumulate
*/
void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result);
-void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, std::map<int, std::string>& input_errors, UniValue& result);
+void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, std::string>& input_errors, UniValue& result);
/**
* Parse a prevtxs UniValue array and get the map of coins from it
diff --git a/src/rpc/request.h b/src/rpc/request.h
index 4761e9e371..1241d999a8 100644
--- a/src/rpc/request.h
+++ b/src/rpc/request.h
@@ -40,7 +40,7 @@ public:
std::string peerAddr;
const util::Ref& context;
- JSONRPCRequest(const util::Ref& context) : id(NullUniValue), params(NullUniValue), fHelp(false), context(context) {}
+ explicit JSONRPCRequest(const util::Ref& context) : id(NullUniValue), params(NullUniValue), fHelp(false), context(context) {}
//! Initializes request information from another request object and the
//! given context. The implementation should be updated if any members are
diff --git a/src/rpc/server.h b/src/rpc/server.h
index b2358ac5b2..7d13edb8b0 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -85,7 +85,6 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface);
*/
void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds);
-typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest);
typedef RPCHelpMan (*RpcMethodFnType)();
class CRPCCommand
@@ -116,14 +115,6 @@ public:
CHECK_NONFATAL(fn().GetArgNames() == args_in);
}
- //! Simplified constructor taking plain rpcfn_type function pointer.
- CRPCCommand(const char* category, const char* name, rpcfn_type fn, std::initializer_list<const char*> args)
- : CRPCCommand(category, name,
- [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn(request); return true; },
- {args.begin(), args.end()}, intptr_t(fn))
- {
- }
-
std::string category;
std::string name;
Actor actor;
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 40dfdb587e..1b21587b6d 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -272,11 +272,12 @@ UniValue DescribeAddress(const CTxDestination& dest)
unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target)
{
- int target = value.get_int();
- if (target < 1 || (unsigned int)target > max_target) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid conf_target, must be between %u - %u", 1, max_target));
+ const int target{value.get_int()};
+ const unsigned int unsigned_target{static_cast<unsigned int>(target)};
+ if (target < 1 || unsigned_target > max_target) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid conf_target, must be between %u and %u", 1, max_target));
}
- return (unsigned int)target;
+ return unsigned_target;
}
RPCErrorCode RPCErrorFromTransactionError(TransactionError terr)
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index 6c0a98cca2..e5ba9ba6d2 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -156,7 +156,7 @@ protected:
uint32_t m_expr_index;
public:
- PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
+ explicit PubkeyProvider(uint32_t exp_index) : m_expr_index(exp_index) {}
virtual ~PubkeyProvider() = default;
@@ -731,7 +731,7 @@ enum class ParseScriptContext {
};
/** Parse a key path, being passed a split list of elements (the first element is ignored). */
-NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error)
+[[nodiscard]] bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error)
{
for (size_t i = 1; i < split.size(); ++i) {
Span<const char> elem = split[i];
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 5735e7df66..bb5a7158a5 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1834,9 +1834,13 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, const std::vector<unsigned char>& program, const CScript& script, uint256& tapleaf_hash)
{
const int path_len = (control.size() - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
+ //! The inner pubkey (x-only, so no Y coordinate parity).
const XOnlyPubKey p{uint256(std::vector<unsigned char>(control.begin() + 1, control.begin() + TAPROOT_CONTROL_BASE_SIZE))};
+ //! The output pubkey (taken from the scriptPubKey).
const XOnlyPubKey q{uint256(program)};
+ // Compute the tapleaf hash.
tapleaf_hash = (CHashWriter(HASHER_TAPLEAF) << uint8_t(control[0] & TAPROOT_LEAF_MASK) << script).GetSHA256();
+ // Compute the Merkle root from the leaf and the provided path.
uint256 k = tapleaf_hash;
for (int i = 0; i < path_len; ++i) {
CHashWriter ss_branch{HASHER_TAPBRANCH};
@@ -1848,7 +1852,9 @@ static bool VerifyTaprootCommitment(const std::vector<unsigned char>& control, c
}
k = ss_branch.GetSHA256();
}
+ // Compute the tweak from the Merkle root and the inner pubkey.
k = (CHashWriter(HASHER_TAPTWEAK) << MakeSpan(p) << k).GetSHA256();
+ // Verify that the output pubkey matches the tweaked inner pubkey, after correcting for parity.
return q.CheckPayToContract(p, k, control[0] & 1);
}
diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp
index 4a6e04f2eb..582341bd3e 100644
--- a/src/script/sigcache.cpp
+++ b/src/script/sigcache.cpp
@@ -46,14 +46,14 @@ public:
}
void
- ComputeEntryECDSA(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey)
+ ComputeEntryECDSA(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const
{
CSHA256 hasher = m_salted_hasher_ecdsa;
hasher.Write(hash.begin(), 32).Write(&pubkey[0], pubkey.size()).Write(&vchSig[0], vchSig.size()).Finalize(entry.begin());
}
void
- ComputeEntrySchnorr(uint256& entry, const uint256 &hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey)
+ ComputeEntrySchnorr(uint256& entry, const uint256 &hash, Span<const unsigned char> sig, const XOnlyPubKey& pubkey) const
{
CSHA256 hasher = m_salted_hasher_schnorr;
hasher.Write(hash.begin(), 32).Write(&pubkey[0], pubkey.size()).Write(sig.data(), sig.size()).Finalize(entry.begin());
@@ -66,7 +66,7 @@ public:
return setValid.contains(entry, erase);
}
- void Set(uint256& entry)
+ void Set(const uint256& entry)
{
boost::unique_lock<boost::shared_mutex> lock(cs_sigcache);
setValid.insert(entry);
diff --git a/src/script/standard.h b/src/script/standard.h
index 721203385e..4d1ef61964 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -28,7 +28,7 @@ protected:
public:
BaseHash() : m_hash() {}
- BaseHash(const HashType& in) : m_hash(in) {}
+ explicit BaseHash(const HashType& in) : m_hash(in) {}
unsigned char* begin()
{
diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml
index bcc8c210f5..ce8d6391b2 100644
--- a/src/secp256k1/.travis.yml
+++ b/src/secp256k1/.travis.yml
@@ -33,7 +33,7 @@ env:
- CFLAGS=-O0 CTIMETEST=no
- ECMULTGENPRECISION=2
- ECMULTGENPRECISION=8
- - RUN_VALGRIND=yes BIGNUM=no ASM=x86_64 EXPERIMENTAL=yes ECDH=yes RECOVERY=yes EXTRAFLAGS="--disable-openssl-tests" BUILD=
+ - RUN_VALGRIND=yes BIGNUM=no ASM=x86_64 ECDH=yes RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes EXTRAFLAGS="--disable-openssl-tests" BUILD=
matrix:
fast_finish: true
include:
@@ -81,7 +81,7 @@ matrix:
- libc6-dbg:i386
# S390x build (big endian system)
- compiler: gcc
- env: HOST=s390x-unknown-linux-gnu ECDH=yes RECOVERY=yes EXPERIMENTAL=yes CTIMETEST=
+ env: HOST=s390x-unknown-linux-gnu ECDH=yes RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes CTIMETEST=
arch: s390x
# We use this to install macOS dependencies instead of the built in `homebrew` plugin,
diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md
index 2602475787..e070937235 100644
--- a/src/secp256k1/README.md
+++ b/src/secp256k1/README.md
@@ -16,7 +16,7 @@ Features:
* Very efficient implementation.
* Suitable for embedded systems.
* Optional module for public key recovery.
-* Optional module for ECDH key exchange (experimental).
+* Optional module for ECDH key exchange.
Experimental features have not received enough scrutiny to satisfy the standard of quality of this library but are made available for testing and review by the community. The APIs of these features should not be considered stable.
diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
index 57595f4499..ece3d655ed 100644
--- a/src/secp256k1/build-aux/m4/bitcoin_secp.m4
+++ b/src/secp256k1/build-aux/m4/bitcoin_secp.m4
@@ -36,16 +36,39 @@ if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then
CPPFLAGS_TEMP="$CPPFLAGS"
CPPFLAGS="$CRYPTO_CPPFLAGS $CPPFLAGS"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>]],[[
- EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
- ECDSA_sign(0, NULL, 0, NULL, NULL, eckey);
+ # if OPENSSL_VERSION_NUMBER < 0x10100000L
+ void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {(void)sig->r; (void)sig->s;}
+ # endif
+
+ unsigned int zero = 0;
+ const unsigned char *zero_ptr = (unsigned char*)&zero;
+ EC_KEY_free(EC_KEY_new_by_curve_name(NID_secp256k1));
+ EC_KEY *eckey = EC_KEY_new();
+ EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1);
+ EC_KEY_set_group(eckey, group);
+ ECDSA_sign(0, NULL, 0, NULL, &zero, eckey);
ECDSA_verify(0, NULL, 0, NULL, 0, eckey);
+ o2i_ECPublicKey(&eckey, &zero_ptr, 0);
+ d2i_ECPrivateKey(&eckey, &zero_ptr, 0);
+ EC_KEY_check_key(eckey);
EC_KEY_free(eckey);
+ EC_GROUP_free(group);
ECDSA_SIG *sig_openssl;
sig_openssl = ECDSA_SIG_new();
+ d2i_ECDSA_SIG(&sig_openssl, &zero_ptr, 0);
+ i2d_ECDSA_SIG(sig_openssl, NULL);
+ ECDSA_SIG_get0(sig_openssl, NULL, NULL);
ECDSA_SIG_free(sig_openssl);
+ const BIGNUM *bignum = BN_value_one();
+ BN_is_negative(bignum);
+ BN_num_bits(bignum);
+ if (sizeof(zero) >= BN_num_bytes(bignum)) {
+ BN_bn2bin(bignum, (unsigned char*)&zero);
+ }
]])],[has_openssl_ec=yes],[has_openssl_ec=no])
AC_MSG_RESULT([$has_openssl_ec])
CPPFLAGS="$CPPFLAGS_TEMP"
diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac
index 5a078e6c81..eb3b449bec 100644
--- a/src/secp256k1/configure.ac
+++ b/src/secp256k1/configure.ac
@@ -122,7 +122,7 @@ AC_ARG_ENABLE(ecmult_static_precomputation,
[use_ecmult_static_precomputation=auto])
AC_ARG_ENABLE(module_ecdh,
- AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]),
+ AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation]),
[enable_module_ecdh=$enableval],
[enable_module_ecdh=no])
@@ -395,8 +395,8 @@ esac
if test x"$use_tests" = x"yes"; then
SECP_OPENSSL_CHECK
- if test x"$has_openssl_ec" = x"yes"; then
- if test x"$enable_openssl_tests" != x"no"; then
+ if test x"$enable_openssl_tests" != x"no" && test x"$has_openssl_ec" = x"yes"; then
+ enable_openssl_tests=yes
AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available])
SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS $CRYPTO_CPPFLAGS"
SECP_TEST_LIBS="$CRYPTO_LIBS"
@@ -406,16 +406,17 @@ if test x"$use_tests" = x"yes"; then
SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32"
;;
esac
- fi
else
if test x"$enable_openssl_tests" = x"yes"; then
AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available])
fi
+ enable_openssl_tests=no
fi
else
if test x"$enable_openssl_tests" = x"yes"; then
AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled])
fi
+ enable_openssl_tests=no
fi
if test x"$set_bignum" = x"gmp"; then
@@ -458,14 +459,10 @@ if test x"$enable_experimental" = x"yes"; then
AC_MSG_NOTICE([******])
AC_MSG_NOTICE([WARNING: experimental build])
AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.])
- AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
AC_MSG_NOTICE([Building extrakeys module: $enable_module_extrakeys])
AC_MSG_NOTICE([Building schnorrsig module: $enable_module_schnorrsig])
AC_MSG_NOTICE([******])
else
- if test x"$enable_module_ecdh" = x"yes"; then
- AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.])
- fi
if test x"$enable_module_extrakeys" = x"yes"; then
AC_MSG_ERROR([extrakeys module is experimental. Use --enable-experimental to allow.])
fi
@@ -507,6 +504,8 @@ echo "Build Options:"
echo " with ecmult precomp = $set_precomp"
echo " with external callbacks = $use_external_default_callbacks"
echo " with benchmarks = $use_benchmark"
+echo " with tests = $use_tests"
+echo " with openssl tests = $enable_openssl_tests"
echo " with coverage = $enable_coverage"
echo " module ecdh = $enable_module_ecdh"
echo " module recovery = $enable_module_recovery"
diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h
index 057a69cf73..a9e8b3c76c 100644
--- a/src/secp256k1/src/ecmult_impl.h
+++ b/src/secp256k1/src/ecmult_impl.h
@@ -443,7 +443,7 @@ struct secp256k1_strauss_state {
struct secp256k1_strauss_point_state* ps;
};
-static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, int num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
+static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, const struct secp256k1_strauss_state *state, secp256k1_gej *r, size_t num, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) {
secp256k1_ge tmpa;
secp256k1_fe Z;
/* Splitted G factors. */
@@ -454,8 +454,8 @@ static void secp256k1_ecmult_strauss_wnaf(const secp256k1_ecmult_context *ctx, c
int bits_ng_128 = 0;
int i;
int bits = 0;
- int np;
- int no = 0;
+ size_t np;
+ size_t no = 0;
for (np = 0; np < num; ++np) {
if (secp256k1_scalar_is_zero(&na[np]) || secp256k1_gej_is_infinity(&a[np])) {
diff --git a/src/shutdown.cpp b/src/shutdown.cpp
index dec497d8ec..a3321a6106 100644
--- a/src/shutdown.cpp
+++ b/src/shutdown.cpp
@@ -5,19 +5,108 @@
#include <shutdown.h>
+#include <config/bitcoin-config.h>
+
+#include <assert.h>
#include <atomic>
+#ifdef WIN32
+#include <condition_variable>
+#else
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
static std::atomic<bool> fRequestShutdown(false);
+#ifdef WIN32
+/** On windows it is possible to simply use a condition variable. */
+std::mutex g_shutdown_mutex;
+std::condition_variable g_shutdown_cv;
+#else
+/** On UNIX-like operating systems use the self-pipe trick.
+ * Index 0 will be the read end of the pipe, index 1 the write end.
+ */
+static int g_shutdown_pipe[2] = {-1, -1};
+#endif
+
+bool InitShutdownState()
+{
+#ifndef WIN32
+#if HAVE_O_CLOEXEC
+ // If we can, make sure that the file descriptors are closed on exec()
+ // to prevent interference.
+ if (pipe2(g_shutdown_pipe, O_CLOEXEC) != 0) {
+ return false;
+ }
+#else
+ if (pipe(g_shutdown_pipe) != 0) {
+ return false;
+ }
+#endif
+#endif
+ return true;
+}
void StartShutdown()
{
+#ifdef WIN32
+ std::unique_lock<std::mutex> lk(g_shutdown_mutex);
fRequestShutdown = true;
+ g_shutdown_cv.notify_one();
+#else
+ // This must be reentrant and safe for calling in a signal handler, so using a condition variable is not safe.
+ // Make sure that the token is only written once even if multiple threads call this concurrently or in
+ // case of a reentrant signal.
+ if (!fRequestShutdown.exchange(true)) {
+ // Write an arbitrary byte to the write end of the shutdown pipe.
+ const char token = 'x';
+ while (true) {
+ int result = write(g_shutdown_pipe[1], &token, 1);
+ if (result < 0) {
+ // Failure. It's possible that the write was interrupted by another signal.
+ // Other errors are unexpected here.
+ assert(errno == EINTR);
+ } else {
+ assert(result == 1);
+ break;
+ }
+ }
+ }
+#endif
}
+
void AbortShutdown()
{
+ if (fRequestShutdown) {
+ // Cancel existing shutdown by waiting for it, this will reset condition flags and remove
+ // the shutdown token from the pipe.
+ WaitForShutdown();
+ }
fRequestShutdown = false;
}
+
bool ShutdownRequested()
{
return fRequestShutdown;
}
+
+void WaitForShutdown()
+{
+#ifdef WIN32
+ std::unique_lock<std::mutex> lk(g_shutdown_mutex);
+ g_shutdown_cv.wait(lk, [] { return fRequestShutdown.load(); });
+#else
+ char token;
+ while (true) {
+ int result = read(g_shutdown_pipe[0], &token, 1);
+ if (result < 0) {
+ // Failure. Check if the read was interrupted by a signal.
+ // Other errors are unexpected here.
+ assert(errno == EINTR);
+ } else {
+ assert(result == 1);
+ break;
+ }
+ }
+#endif
+}
diff --git a/src/shutdown.h b/src/shutdown.h
index 3ed851c789..23f84179e9 100644
--- a/src/shutdown.h
+++ b/src/shutdown.h
@@ -6,8 +6,25 @@
#ifndef BITCOIN_SHUTDOWN_H
#define BITCOIN_SHUTDOWN_H
+/** Initialize shutdown state. This must be called before using either StartShutdown(),
+ * AbortShutdown() or WaitForShutdown(). Calling ShutdownRequested() is always safe.
+ */
+bool InitShutdownState();
+
+/** Request shutdown of the application. */
void StartShutdown();
+
+/** Clear shutdown flag. Only use this during init (before calling WaitForShutdown in any
+ * thread), or in the unit tests. Calling it in other circumstances will cause a race condition.
+ */
void AbortShutdown();
+
+/** Returns true if a shutdown is requested, false otherwise. */
bool ShutdownRequested();
+/** Wait for StartShutdown to be called in any thread. This can only be used
+ * from a single thread.
+ */
+void WaitForShutdown();
+
#endif
diff --git a/src/span.h b/src/span.h
index 4afb383a59..830164514b 100644
--- a/src/span.h
+++ b/src/span.h
@@ -18,6 +18,16 @@
#define ASSERT_IF_DEBUG(x)
#endif
+#if defined(__clang__)
+#if __has_attribute(lifetimebound)
+#define SPAN_ATTR_LIFETIMEBOUND [[clang::lifetimebound]]
+#else
+#define SPAN_ATTR_LIFETIMEBOUND
+#endif
+#else
+#define SPAN_ATTR_LIFETIMEBOUND
+#endif
+
/** A Span is an object that can refer to a contiguous sequence of objects.
*
* It implements a subset of C++20's std::span.
@@ -84,6 +94,14 @@ class Span
C* m_data;
std::size_t m_size;
+ template <class T>
+ struct is_Span_int : public std::false_type {};
+ template <class T>
+ struct is_Span_int<Span<T>> : public std::true_type {};
+ template <class T>
+ struct is_Span : public is_Span_int<typename std::remove_cv<T>::type>{};
+
+
public:
constexpr Span() noexcept : m_data(nullptr), m_size(0) {}
@@ -134,8 +152,19 @@ public:
* To prevent surprises, only Spans for constant value types are supported when passing in temporaries.
* Note that this restriction does not exist when converting arrays or other Spans (see above).
*/
- template <typename V, typename std::enable_if<(std::is_const<C>::value || std::is_lvalue_reference<V>::value) && std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value && std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, int>::type = 0>
- constexpr Span(V&& v) noexcept : m_data(v.data()), m_size(v.size()) {}
+ template <typename V>
+ constexpr Span(V& other SPAN_ATTR_LIFETIMEBOUND,
+ typename std::enable_if<!is_Span<V>::value &&
+ std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value &&
+ std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
+ : m_data(other.data()), m_size(other.size()){}
+
+ template <typename V>
+ constexpr Span(const V& other SPAN_ATTR_LIFETIMEBOUND,
+ typename std::enable_if<!is_Span<V>::value &&
+ std::is_convertible<typename std::remove_pointer<decltype(std::declval<const V&>().data())>::type (*)[], C (*)[]>::value &&
+ std::is_convertible<decltype(std::declval<const V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
+ : m_data(other.data()), m_size(other.size()){}
constexpr C* data() const noexcept { return m_data; }
constexpr C* begin() const noexcept { return m_data; }
@@ -192,9 +221,9 @@ public:
/** MakeSpan for arrays: */
template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
/** MakeSpan for temporaries / rvalue references, only supporting const output. */
-template <typename V> constexpr auto MakeSpan(V&& v) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); }
+template <typename V> constexpr auto MakeSpan(V&& v SPAN_ATTR_LIFETIMEBOUND) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); }
/** MakeSpan for (lvalue) references, supporting mutable output. */
-template <typename V> constexpr auto MakeSpan(V& v) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
+template <typename V> constexpr auto MakeSpan(V& v SPAN_ATTR_LIFETIMEBOUND) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
/** Pop the last element off a span, and return a reference to that element. */
template <typename T>
diff --git a/src/sync.cpp b/src/sync.cpp
index 322198a852..acfbe8fe29 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -13,10 +13,14 @@
#include <util/strencodings.h>
#include <util/threadnames.h>
+#include <boost/thread/mutex.hpp>
+
#include <map>
+#include <mutex>
#include <set>
#include <system_error>
#include <thread>
+#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
@@ -135,16 +139,52 @@ static void potential_deadlock_detected(const LockPair& mismatch, const LockStac
throw std::logic_error(strprintf("potential deadlock detected: %s -> %s -> %s", mutex_b, mutex_a, mutex_b));
}
-static void push_lock(void* c, const CLockLocation& locklocation)
+static void double_lock_detected(const void* mutex, const LockStack& lock_stack)
+{
+ LogPrintf("DOUBLE LOCK DETECTED\n");
+ LogPrintf("Lock order:\n");
+ for (const LockStackItem& i : lock_stack) {
+ if (i.first == mutex) {
+ LogPrintf(" (*)"); /* Continued */
+ }
+ LogPrintf(" %s\n", i.second.ToString());
+ }
+ if (g_debug_lockorder_abort) {
+ tfm::format(std::cerr,
+ "Assertion failed: detected double lock for %s, details in debug log.\n",
+ lock_stack.back().second.ToString());
+ abort();
+ }
+ throw std::logic_error("double lock detected");
+}
+
+template <typename MutexType>
+static void push_lock(MutexType* c, const CLockLocation& locklocation)
{
+ constexpr bool is_recursive_mutex =
+ std::is_base_of<RecursiveMutex, MutexType>::value ||
+ std::is_base_of<std::recursive_mutex, MutexType>::value;
+
LockData& lockdata = GetLockData();
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
lock_stack.emplace_back(c, locklocation);
- for (const LockStackItem& i : lock_stack) {
- if (i.first == c)
- break;
+ for (size_t j = 0; j < lock_stack.size() - 1; ++j) {
+ const LockStackItem& i = lock_stack[j];
+ if (i.first == c) {
+ if (is_recursive_mutex) {
+ break;
+ }
+ // It is not a recursive mutex and it appears in the stack two times:
+ // at position `j` and at the end (which we added just before this loop).
+ // Can't allow locking the same (non-recursive) mutex two times from the
+ // same thread as that results in an undefined behavior.
+ auto lock_stack_copy = lock_stack;
+ lock_stack.pop_back();
+ double_lock_detected(c, lock_stack_copy);
+ // double_lock_detected() does not return.
+ }
const LockPair p1 = std::make_pair(i.first, c);
if (lockdata.lockorders.count(p1))
@@ -175,27 +215,41 @@ static void pop_lock()
}
}
-void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
+template <typename MutexType>
+void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry)
{
push_lock(cs, CLockLocation(pszName, pszFile, nLine, fTry, util::ThreadGetInternalName()));
}
+template void EnterCritical(const char*, const char*, int, Mutex*, bool);
+template void EnterCritical(const char*, const char*, int, RecursiveMutex*, bool);
+template void EnterCritical(const char*, const char*, int, std::mutex*, bool);
+template void EnterCritical(const char*, const char*, int, std::recursive_mutex*, bool);
+template void EnterCritical(const char*, const char*, int, boost::mutex*, bool);
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line)
{
- {
- LockData& lockdata = GetLockData();
- std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
-
- const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
- if (!lock_stack.empty()) {
- const auto& lastlock = lock_stack.back();
- if (lastlock.first == cs) {
- lockname = lastlock.second.Name();
- return;
- }
+ LockData& lockdata = GetLockData();
+ std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
+
+ const LockStack& lock_stack = lockdata.m_lock_stacks[std::this_thread::get_id()];
+ if (!lock_stack.empty()) {
+ const auto& lastlock = lock_stack.back();
+ if (lastlock.first == cs) {
+ lockname = lastlock.second.Name();
+ return;
}
}
- throw std::system_error(EPERM, std::generic_category(), strprintf("%s:%s %s was not most recent critical section locked", file, line, guardname));
+
+ LogPrintf("INCONSISTENT LOCK ORDER DETECTED\n");
+ LogPrintf("Current lock order (least recent first) is:\n");
+ for (const LockStackItem& i : lock_stack) {
+ LogPrintf(" %s\n", i.second.ToString());
+ }
+ if (g_debug_lockorder_abort) {
+ tfm::format(std::cerr, "%s:%s %s was not most recent critical section locked, details in debug log.\n", file, line, guardname);
+ abort();
+ }
+ throw std::logic_error(strprintf("%s was not most recent critical section locked", guardname));
}
void LeaveCritical()
diff --git a/src/sync.h b/src/sync.h
index 41f4e43bdd..749bf5575c 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -48,7 +48,8 @@ LEAVE_CRITICAL_SECTION(mutex); // no RAII
///////////////////////////////
#ifdef DEBUG_LOCKORDER
-void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
+template <typename MutexType>
+void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false);
void LeaveCritical();
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
std::string LocksHeld();
@@ -66,7 +67,8 @@ bool LockStackEmpty();
*/
extern bool g_debug_lockorder_abort;
#else
-inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
+template <typename MutexType>
+inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
inline void LeaveCritical() {}
inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
template <typename MutexType>
@@ -135,7 +137,7 @@ class SCOPED_LOCKABLE UniqueLock : public Base
private:
void Enter(const char* pszName, const char* pszFile, int nLine)
{
- EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex()));
+ EnterCritical(pszName, pszFile, nLine, Base::mutex());
#ifdef DEBUG_LOCKCONTENTION
if (!Base::try_lock()) {
PrintLockContention(pszName, pszFile, nLine);
@@ -148,7 +150,7 @@ private:
bool TryEnter(const char* pszName, const char* pszFile, int nLine)
{
- EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex()), true);
+ EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
Base::try_lock();
if (!Base::owns_lock())
LeaveCritical();
@@ -205,7 +207,7 @@ public:
~reverse_lock() {
templock.swap(lock);
- EnterCritical(lockname.c_str(), file.c_str(), line, (void*)lock.mutex());
+ EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
lock.lock();
}
@@ -236,14 +238,16 @@ using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove
#define ENTER_CRITICAL_SECTION(cs) \
{ \
- EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
+ EnterCritical(#cs, __FILE__, __LINE__, &cs); \
(cs).lock(); \
}
-#define LEAVE_CRITICAL_SECTION(cs) \
- { \
- (cs).unlock(); \
- LeaveCritical(); \
+#define LEAVE_CRITICAL_SECTION(cs) \
+ { \
+ std::string lockname; \
+ CheckLastCritical((void*)(&cs), lockname, #cs, __FILE__, __LINE__); \
+ (cs).unlock(); \
+ LeaveCritical(); \
}
//! Run code while locking a mutex.
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 25fdd64568..37ff8a9afe 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -71,7 +71,7 @@ public:
}
// Simulates connection failure so that we can test eviction of offline nodes
- void SimConnFail(CService& addr)
+ void SimConnFail(const CService& addr)
{
LOCK(cs);
int64_t nLastSuccess = 1;
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
index e20900ed13..c16519a6b1 100644
--- a/src/test/amount_tests.cpp
+++ b/src/test/amount_tests.cpp
@@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(BinaryOperatorTest)
BOOST_CHECK(a <= a);
BOOST_CHECK(b >= a);
BOOST_CHECK(b >= b);
- // a should be 0.00000002 BTC/kB now
+ // a should be 0.00000002 BTC/kvB now
a += a;
BOOST_CHECK(a == b);
}
@@ -107,7 +107,9 @@ BOOST_AUTO_TEST_CASE(ToStringTest)
{
CFeeRate feeRate;
feeRate = CFeeRate(1);
- BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kB");
+ BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kvB");
+ BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::BTC_KVB), "0.00000001 BTC/kvB");
+ BOOST_CHECK_EQUAL(feeRate.ToString(FeeEstimateMode::SAT_VB), "0.001 sat/vB");
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
index d519eca859..3f7c5e99ee 100644
--- a/src/test/base32_tests.cpp
+++ b/src/test/base32_tests.cpp
@@ -6,6 +6,9 @@
#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
+#include <string>
+
+using namespace std::literals;
BOOST_FIXTURE_TEST_SUITE(base32_tests, BasicTestingSetup)
@@ -26,14 +29,14 @@ BOOST_AUTO_TEST_CASE(base32_testvectors)
// Decoding strings with embedded NUL characters should fail
bool failure;
- (void)DecodeBase32(std::string("invalid", 7), &failure);
- BOOST_CHECK_EQUAL(failure, true);
- (void)DecodeBase32(std::string("AWSX3VPP", 8), &failure);
- BOOST_CHECK_EQUAL(failure, false);
- (void)DecodeBase32(std::string("AWSX3VPP\0invalid", 16), &failure);
- BOOST_CHECK_EQUAL(failure, true);
- (void)DecodeBase32(std::string("AWSX3VPPinvalid", 15), &failure);
- BOOST_CHECK_EQUAL(failure, true);
+ (void)DecodeBase32("invalid\0"s, &failure); // correct size, invalid due to \0
+ BOOST_CHECK(failure);
+ (void)DecodeBase32("AWSX3VPP"s, &failure); // valid
+ BOOST_CHECK(!failure);
+ (void)DecodeBase32("AWSX3VPP\0invalid"s, &failure); // correct size, invalid due to \0
+ BOOST_CHECK(failure);
+ (void)DecodeBase32("AWSX3VPPinvalid"s, &failure); // invalid size
+ BOOST_CHECK(failure);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 6a636f2574..e55d6b3b19 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -12,7 +12,9 @@
#include <univalue.h>
#include <boost/test/unit_test.hpp>
+#include <string>
+using namespace std::literals;
extern UniValue read_json(const std::string& jsondata);
@@ -58,14 +60,14 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest);
}
- BOOST_CHECK(!DecodeBase58("invalid", result, 100));
- BOOST_CHECK(!DecodeBase58(std::string("invalid"), result, 100));
- BOOST_CHECK(!DecodeBase58(std::string("\0invalid", 8), result, 100));
+ BOOST_CHECK(!DecodeBase58("invalid"s, result, 100));
+ BOOST_CHECK(!DecodeBase58("invalid\0"s, result, 100));
+ BOOST_CHECK(!DecodeBase58("\0invalid"s, result, 100));
- BOOST_CHECK(DecodeBase58(std::string("good", 4), result, 100));
- BOOST_CHECK(!DecodeBase58(std::string("bad0IOl", 7), result, 100));
- BOOST_CHECK(!DecodeBase58(std::string("goodbad0IOl", 11), result, 100));
- BOOST_CHECK(!DecodeBase58(std::string("good\0bad0IOl", 12), result, 100));
+ BOOST_CHECK(DecodeBase58("good"s, result, 100));
+ BOOST_CHECK(!DecodeBase58("bad0IOl"s, result, 100));
+ BOOST_CHECK(!DecodeBase58("goodbad0IOl"s, result, 100));
+ BOOST_CHECK(!DecodeBase58("good\0bad0IOl"s, result, 100));
// check that DecodeBase58 skips whitespace, but still fails with unexpected non-whitespace at the end.
BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result, 3));
@@ -73,10 +75,10 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
std::vector<unsigned char> expected = ParseHex("971a55");
BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
- BOOST_CHECK(DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh", 21), result, 100));
- BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oi", 21), result, 100));
- BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh0IOl", 25), result, 100));
- BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh\00IOl", 26), result, 100));
+ BOOST_CHECK(DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh"s, result, 100));
+ BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oi"s, result, 100));
+ BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh0IOl"s, result, 100));
+ BOOST_CHECK(!DecodeBase58Check("3vQB7B6MrGQZaxCuFg4oh\0" "0IOl"s, result, 100));
}
BOOST_AUTO_TEST_CASE(base58_random_encode_decode)
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index 5927eab6cf..bb8d102bd0 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -6,6 +6,9 @@
#include <util/strencodings.h>
#include <boost/test/unit_test.hpp>
+#include <string>
+
+using namespace std::literals;
BOOST_FIXTURE_TEST_SUITE(base64_tests, BasicTestingSetup)
@@ -23,14 +26,14 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
// Decoding strings with embedded NUL characters should fail
bool failure;
- (void)DecodeBase64(std::string("invalid", 7), &failure);
- BOOST_CHECK_EQUAL(failure, true);
- (void)DecodeBase64(std::string("nQB/pZw=", 8), &failure);
- BOOST_CHECK_EQUAL(failure, false);
- (void)DecodeBase64(std::string("nQB/pZw=\0invalid", 16), &failure);
- BOOST_CHECK_EQUAL(failure, true);
- (void)DecodeBase64(std::string("nQB/pZw=invalid", 15), &failure);
- BOOST_CHECK_EQUAL(failure, true);
+ (void)DecodeBase64("invalid\0"s, &failure);
+ BOOST_CHECK(failure);
+ (void)DecodeBase64("nQB/pZw="s, &failure);
+ BOOST_CHECK(!failure);
+ (void)DecodeBase64("nQB/pZw=\0invalid"s, &failure);
+ BOOST_CHECK(failure);
+ (void)DecodeBase64("nQB/pZw=invalid\0"s, &failure);
+ BOOST_CHECK(failure);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 173ec5e3d9..6bfcf242d0 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -38,7 +38,7 @@ class CCoinsViewTest : public CCoinsView
std::map<COutPoint, Coin> map_;
public:
- NODISCARD bool GetCoin(const COutPoint& outpoint, Coin& coin) const override
+ [[nodiscard]] bool GetCoin(const COutPoint& outpoint, Coin& coin) const override
{
std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint);
if (it == map_.end()) {
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
index 712567ac0d..8f6fdd04d0 100644
--- a/src/test/denialofservice_tests.cpp
+++ b/src/test/denialofservice_tests.cpp
@@ -80,7 +80,8 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
const CChainParams& chainparams = Params();
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
@@ -88,7 +89,6 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode1);
- dummyNode1.nVersion = 1;
dummyNode1.fSuccessfullyConnected = true;
// This test requires that we have a chain with non-zero work.
@@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
SetMockTime(0);
bool dummy;
- peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
+ peerLogic->FinalizeNode(dummyNode1, dummy);
}
static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &peerLogic, CConnmanTest* connman)
@@ -141,7 +141,6 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &pee
node.SetCommonVersion(PROTOCOL_VERSION);
peerLogic.InitializeNode(&node);
- node.nVersion = 1;
node.fSuccessfullyConnected = true;
connman->AddNode(node);
@@ -151,7 +150,8 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
const CChainParams& chainparams = Params();
auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
CConnman::Options options;
@@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
bool dummy;
for (const CNode *node : vNodes) {
- peerLogic->FinalizeNode(node->GetId(), dummy);
+ peerLogic->FinalizeNode(*node, dummy);
}
connman->ClearNodes();
@@ -224,14 +224,14 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
const CChainParams& chainparams = Params();
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", ConnectionType::INBOUND);
dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode1);
- dummyNode1.nVersion = 1;
dummyNode1.fSuccessfullyConnected = true;
peerLogic->Misbehaving(dummyNode1.GetId(), DISCOURAGEMENT_THRESHOLD, /* message */ ""); // Should be discouraged
{
@@ -245,7 +245,6 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", ConnectionType::INBOUND);
dummyNode2.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode2);
- dummyNode2.nVersion = 1;
dummyNode2.fSuccessfullyConnected = true;
peerLogic->Misbehaving(dummyNode2.GetId(), DISCOURAGEMENT_THRESHOLD - 1, /* message */ "");
{
@@ -263,8 +262,8 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
BOOST_CHECK(banman->IsDiscouraged(addr2)); // to be discouraged now
bool dummy;
- peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
- peerLogic->FinalizeNode(dummyNode2.GetId(), dummy);
+ peerLogic->FinalizeNode(dummyNode1, dummy);
+ peerLogic->FinalizeNode(dummyNode2, dummy);
}
BOOST_AUTO_TEST_CASE(DoS_bantime)
@@ -272,7 +271,8 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
const CChainParams& chainparams = Params();
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
- auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
+ auto peerLogic = std::make_unique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler,
+ *m_node.chainman, *m_node.mempool, false);
banman->ClearBanned();
int64_t nStartTime = GetTime();
@@ -282,7 +282,6 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", ConnectionType::INBOUND);
dummyNode.SetCommonVersion(PROTOCOL_VERSION);
peerLogic->InitializeNode(&dummyNode);
- dummyNode.nVersion = 1;
dummyNode.fSuccessfullyConnected = true;
peerLogic->Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD, /* message */ "");
@@ -293,7 +292,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
BOOST_CHECK(banman->IsDiscouraged(addr));
bool dummy;
- peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
+ peerLogic->FinalizeNode(dummyNode, dummy);
}
static CTransactionRef RandomOrphan()
diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp
index a455992b13..c6cfbd8d30 100644
--- a/src/test/fuzz/addition_overflow.cpp
+++ b/src/test/fuzz/addition_overflow.cpp
@@ -14,7 +14,7 @@
#if __has_builtin(__builtin_add_overflow)
#define HAVE_BUILTIN_ADD_OVERFLOW
#endif
-#elif defined(__GNUC__) && (__GNUC__ >= 5)
+#elif defined(__GNUC__)
#define HAVE_BUILTIN_ADD_OVERFLOW
#endif
@@ -40,7 +40,7 @@ void TestAdditionOverflow(FuzzedDataProvider& fuzzed_data_provider)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(addition_overflow)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
TestAdditionOverflow<int64_t>(fuzzed_data_provider);
diff --git a/src/test/fuzz/addrdb.cpp b/src/test/fuzz/addrdb.cpp
index 16b1cb755a..d15c785673 100644
--- a/src/test/fuzz/addrdb.cpp
+++ b/src/test/fuzz/addrdb.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(addrdb)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
new file mode 100644
index 0000000000..af9080b5e9
--- /dev/null
+++ b/src/test/fuzz/addrman.cpp
@@ -0,0 +1,129 @@
+// 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.
+
+#include <addrdb.h>
+#include <addrman.h>
+#include <chainparams.h>
+#include <merkleblock.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <time.h>
+#include <util/asmap.h>
+
+#include <cstdint>
+#include <optional>
+#include <string>
+#include <vector>
+
+void initialize_addrman()
+{
+ SelectParams(CBaseChainParams::REGTEST);
+}
+
+class CAddrManDeterministic : public CAddrMan
+{
+public:
+ void MakeDeterministic(const uint256& random_seed)
+ {
+ insecure_rand = FastRandomContext{random_seed};
+ Clear();
+ }
+};
+
+FUZZ_TARGET_INIT(addrman, initialize_addrman)
+{
+ FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
+ CAddrManDeterministic addr_man;
+ addr_man.MakeDeterministic(ConsumeUInt256(fuzzed_data_provider));
+ if (fuzzed_data_provider.ConsumeBool()) {
+ addr_man.m_asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
+ if (!SanityCheckASMap(addr_man.m_asmap)) {
+ addr_man.m_asmap.clear();
+ }
+ }
+ while (fuzzed_data_provider.ConsumeBool()) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 11)) {
+ case 0: {
+ addr_man.Clear();
+ break;
+ }
+ case 1: {
+ addr_man.ResolveCollisions();
+ break;
+ }
+ case 2: {
+ (void)addr_man.SelectTriedCollision();
+ break;
+ }
+ case 3: {
+ (void)addr_man.Select(fuzzed_data_provider.ConsumeBool());
+ break;
+ }
+ case 4: {
+ (void)addr_man.GetAddr(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
+ break;
+ }
+ case 5: {
+ const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider);
+ const std::optional<CNetAddr> opt_net_addr = ConsumeDeserializable<CNetAddr>(fuzzed_data_provider);
+ if (opt_address && opt_net_addr) {
+ addr_man.Add(*opt_address, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 100000000));
+ }
+ break;
+ }
+ case 6: {
+ std::vector<CAddress> addresses;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider);
+ if (!opt_address) {
+ break;
+ }
+ addresses.push_back(*opt_address);
+ }
+ 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));
+ }
+ break;
+ }
+ case 7: {
+ const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
+ if (opt_service) {
+ addr_man.Good(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider));
+ }
+ break;
+ }
+ case 8: {
+ 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));
+ }
+ break;
+ }
+ case 9: {
+ const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
+ if (opt_service) {
+ addr_man.Connected(*opt_service, ConsumeTime(fuzzed_data_provider));
+ }
+ break;
+ }
+ case 10: {
+ const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider);
+ if (opt_service) {
+ addr_man.SetServices(*opt_service, ServiceFlags{fuzzed_data_provider.ConsumeIntegral<uint64_t>()});
+ }
+ break;
+ }
+ case 11: {
+ (void)addr_man.Check();
+ break;
+ }
+ }
+ }
+ (void)addr_man.size();
+ CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION);
+ data_stream << addr_man;
+}
diff --git a/src/test/fuzz/asmap.cpp b/src/test/fuzz/asmap.cpp
index e3aefa18a3..4c5bc0cbf2 100644
--- a/src/test/fuzz/asmap.cpp
+++ b/src/test/fuzz/asmap.cpp
@@ -27,7 +27,7 @@ static const std::vector<bool> IPV4_PREFIX_ASMAP = {
true, true, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true // Match 0xFF
};
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(asmap)
{
// Encoding: [7 bits: asmap size] [1 bit: ipv6?] [3-130 bytes: asmap] [4 or 16 bytes: addr]
if (buffer.size() < 1 + 3 + 4) return;
diff --git a/src/test/fuzz/asmap_direct.cpp b/src/test/fuzz/asmap_direct.cpp
index 2d21eff9d6..8b7822dc16 100644
--- a/src/test/fuzz/asmap_direct.cpp
+++ b/src/test/fuzz/asmap_direct.cpp
@@ -11,7 +11,7 @@
#include <assert.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(asmap_direct)
{
// Encoding: [asmap using 1 bit / byte] 0xFF [addr using 1 bit / byte]
std::optional<size_t> sep_pos_opt;
diff --git a/src/test/fuzz/autofile.cpp b/src/test/fuzz/autofile.cpp
index 7ea0bdd2a7..eb3424ef28 100644
--- a/src/test/fuzz/autofile.cpp
+++ b/src/test/fuzz/autofile.cpp
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(autofile)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp
index fc4a1d9261..cf69fa0722 100644
--- a/src/test/fuzz/banman.cpp
+++ b/src/test/fuzz/banman.cpp
@@ -24,14 +24,15 @@ int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept
}
} // namespace
-void initialize()
+void initialize_banman()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(banman, initialize_banman)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
const fs::path banlist_file = GetDataDir() / "fuzzed_banlist.dat";
fs::remove(banlist_file);
{
diff --git a/src/test/fuzz/base_encode_decode.cpp b/src/test/fuzz/base_encode_decode.cpp
index 8d49f93c2f..4470e13a61 100644
--- a/src/test/fuzz/base_encode_decode.cpp
+++ b/src/test/fuzz/base_encode_decode.cpp
@@ -14,7 +14,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(base_encode_decode)
{
const std::string random_encoded_string(buffer.begin(), buffer.end());
diff --git a/src/test/fuzz/bech32.cpp b/src/test/fuzz/bech32.cpp
index 8b91f9bc96..b1a485e12e 100644
--- a/src/test/fuzz/bech32.cpp
+++ b/src/test/fuzz/bech32.cpp
@@ -13,7 +13,7 @@
#include <utility>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(bech32)
{
const std::string random_string(buffer.begin(), buffer.end());
const std::pair<std::string, std::vector<uint8_t>> r1 = bech32::Decode(random_string);
diff --git a/src/test/fuzz/block.cpp b/src/test/fuzz/block.cpp
index 91bd34a251..65a33de4b4 100644
--- a/src/test/fuzz/block.cpp
+++ b/src/test/fuzz/block.cpp
@@ -17,13 +17,13 @@
#include <cassert>
#include <string>
-void initialize()
+void initialize_block()
{
static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(block, initialize_block)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
CBlock block;
diff --git a/src/test/fuzz/block_header.cpp b/src/test/fuzz/block_header.cpp
index 09c2b4a951..c73270dcb3 100644
--- a/src/test/fuzz/block_header.cpp
+++ b/src/test/fuzz/block_header.cpp
@@ -14,7 +14,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(block_header)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CBlockHeader> block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
diff --git a/src/test/fuzz/blockfilter.cpp b/src/test/fuzz/blockfilter.cpp
index 7232325a20..7fa06085f8 100644
--- a/src/test/fuzz/blockfilter.cpp
+++ b/src/test/fuzz/blockfilter.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(blockfilter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<BlockFilter> block_filter = ConsumeDeserializable<BlockFilter>(fuzzed_data_provider);
diff --git a/src/test/fuzz/bloom_filter.cpp b/src/test/fuzz/bloom_filter.cpp
index d955c71bc9..c0c66c564b 100644
--- a/src/test/fuzz/bloom_filter.cpp
+++ b/src/test/fuzz/bloom_filter.cpp
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(bloom_filter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/buffered_file.cpp b/src/test/fuzz/buffered_file.cpp
index e575640be5..23e197456a 100644
--- a/src/test/fuzz/buffered_file.cpp
+++ b/src/test/fuzz/buffered_file.cpp
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(buffered_file)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp
index 47c71850ce..9f7074b423 100644
--- a/src/test/fuzz/chain.cpp
+++ b/src/test/fuzz/chain.cpp
@@ -11,7 +11,7 @@
#include <optional>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(chain)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
std::optional<CDiskBlockIndex> disk_block_index = ConsumeDeserializable<CDiskBlockIndex>(fuzzed_data_provider);
diff --git a/src/test/fuzz/checkqueue.cpp b/src/test/fuzz/checkqueue.cpp
index c69043bb6b..0b16f0f0d5 100644
--- a/src/test/fuzz/checkqueue.cpp
+++ b/src/test/fuzz/checkqueue.cpp
@@ -32,7 +32,7 @@ struct DumbCheck {
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(checkqueue)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp
index c186bef7ae..1ae421493e 100644
--- a/src/test/fuzz/coins_view.cpp
+++ b/src/test/fuzz/coins_view.cpp
@@ -34,14 +34,14 @@ bool operator==(const Coin& a, const Coin& b)
}
} // namespace
-void initialize()
+void initialize_coins_view()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
CCoinsView backend_coins_view;
@@ -229,7 +229,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 1: {
- (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache);
+ (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache, false);
+ (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache, true);
break;
}
case 2: {
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
new file mode 100644
index 0000000000..c5702cf98e
--- /dev/null
+++ b/src/test/fuzz/connman.cpp
@@ -0,0 +1,157 @@
+// 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.
+
+#include <chainparams.h>
+#include <chainparamsbase.h>
+#include <net.h>
+#include <netaddress.h>
+#include <protocol.h>
+#include <test/fuzz/FuzzedDataProvider.h>
+#include <test/fuzz/fuzz.h>
+#include <test/fuzz/util.h>
+#include <util/translation.h>
+
+#include <cstdint>
+#include <vector>
+
+void initialize_connman()
+{
+ InitializeFuzzingContext();
+}
+
+FUZZ_TARGET_INIT(connman, initialize_connman)
+{
+ FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
+ CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeBool()};
+ CAddress random_address;
+ CNetAddr random_netaddr;
+ CNode random_node = ConsumeNode(fuzzed_data_provider);
+ CService random_service;
+ CSubNet random_subnet;
+ std::string random_string;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 28)) {
+ case 0:
+ random_address = ConsumeAddress(fuzzed_data_provider);
+ break;
+ case 1:
+ random_netaddr = ConsumeNetAddr(fuzzed_data_provider);
+ break;
+ case 2:
+ random_service = ConsumeService(fuzzed_data_provider);
+ break;
+ case 3:
+ random_subnet = ConsumeSubNet(fuzzed_data_provider);
+ break;
+ case 4:
+ random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
+ break;
+ case 5: {
+ std::vector<CAddress> addresses;
+ while (fuzzed_data_provider.ConsumeBool()) {
+ addresses.push_back(ConsumeAddress(fuzzed_data_provider));
+ }
+ // Limit nTimePenalty to int32_t to avoid signed integer overflow
+ (void)connman.AddNewAddresses(addresses, ConsumeAddress(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<int32_t>());
+ break;
+ }
+ case 6:
+ connman.AddNode(random_string);
+ break;
+ case 7:
+ connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ break;
+ case 8:
+ connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>());
+ break;
+ case 9:
+ connman.DisconnectNode(random_netaddr);
+ break;
+ case 10:
+ connman.DisconnectNode(random_string);
+ break;
+ case 11:
+ connman.DisconnectNode(random_subnet);
+ break;
+ case 12:
+ connman.ForEachNode([](auto) {});
+ break;
+ case 13:
+ connman.ForEachNodeThen([](auto) {}, []() {});
+ break;
+ case 14:
+ (void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral<NodeId>(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); });
+ break;
+ case 15:
+ (void)connman.GetAddresses(fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>());
+ break;
+ case 16: {
+ (void)connman.GetAddresses(random_node, fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>());
+ break;
+ }
+ case 17:
+ (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ break;
+ case 18:
+ (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({CConnman::CONNECTIONS_NONE, CConnman::CONNECTIONS_IN, CConnman::CONNECTIONS_OUT, CConnman::CONNECTIONS_ALL}));
+ break;
+ case 19:
+ connman.MarkAddressGood(random_address);
+ break;
+ case 20:
+ (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool());
+ break;
+ case 21:
+ // Limit now to int32_t to avoid signed integer overflow
+ (void)connman.PoissonNextSendInbound(fuzzed_data_provider.ConsumeIntegral<int32_t>(), fuzzed_data_provider.ConsumeIntegral<int>());
+ break;
+ case 22: {
+ CSerializedNetMsg serialized_net_msg;
+ serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::COMMAND_SIZE);
+ serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
+ connman.PushMessage(&random_node, std::move(serialized_net_msg));
+ break;
+ }
+ case 23:
+ connman.RemoveAddedNode(random_string);
+ break;
+ case 24: {
+ const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
+ if (SanityCheckASMap(asmap)) {
+ connman.SetAsmap(asmap);
+ }
+ break;
+ }
+ case 25:
+ connman.SetBestHeight(fuzzed_data_provider.ConsumeIntegral<int>());
+ break;
+ case 26:
+ connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
+ break;
+ case 27:
+ connman.SetServices(random_service, static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()));
+ break;
+ case 28:
+ connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());
+ break;
+ }
+ }
+ (void)connman.GetAddedNodeInfo();
+ (void)connman.GetBestHeight();
+ (void)connman.GetExtraFullOutboundCount();
+ (void)connman.GetLocalServices();
+ (void)connman.GetMaxOutboundTarget();
+ (void)connman.GetMaxOutboundTimeframe();
+ (void)connman.GetMaxOutboundTimeLeftInCycle();
+ (void)connman.GetNetworkActive();
+ std::vector<CNodeStats> stats;
+ connman.GetNodeStats(stats);
+ (void)connman.GetOutboundTargetBytesLeft();
+ (void)connman.GetReceiveFloodSize();
+ (void)connman.GetTotalBytesRecv();
+ (void)connman.GetTotalBytesSent();
+ (void)connman.GetTryNewOutboundPeer();
+ (void)connman.GetUseAddrmanOutgoing();
+}
diff --git a/src/test/fuzz/crypto.cpp b/src/test/fuzz/crypto.cpp
index 664e65accc..4783cc1c43 100644
--- a/src/test/fuzz/crypto.cpp
+++ b/src/test/fuzz/crypto.cpp
@@ -17,7 +17,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
std::vector<uint8_t> data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
diff --git a/src/test/fuzz/crypto_aes256.cpp b/src/test/fuzz/crypto_aes256.cpp
index ae14073c96..ccabd1f7dc 100644
--- a/src/test/fuzz/crypto_aes256.cpp
+++ b/src/test/fuzz/crypto_aes256.cpp
@@ -11,7 +11,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_aes256)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::vector<uint8_t> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, AES256_KEYSIZE);
diff --git a/src/test/fuzz/crypto_aes256cbc.cpp b/src/test/fuzz/crypto_aes256cbc.cpp
index 52983c7e79..6d4138e546 100644
--- a/src/test/fuzz/crypto_aes256cbc.cpp
+++ b/src/test/fuzz/crypto_aes256cbc.cpp
@@ -11,7 +11,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_aes256cbc)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::vector<uint8_t> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, AES256_KEYSIZE);
diff --git a/src/test/fuzz/crypto_chacha20.cpp b/src/test/fuzz/crypto_chacha20.cpp
index b7438d312d..d751466f11 100644
--- a/src/test/fuzz/crypto_chacha20.cpp
+++ b/src/test/fuzz/crypto_chacha20.cpp
@@ -10,7 +10,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_chacha20)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
index 48e4263f27..631af9c70d 100644
--- a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
+++ b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp
@@ -13,7 +13,7 @@
#include <limits>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_chacha20_poly1305_aead)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/crypto_common.cpp b/src/test/fuzz/crypto_common.cpp
index 7ccb125216..8e07dfedb9 100644
--- a/src/test/fuzz/crypto_common.cpp
+++ b/src/test/fuzz/crypto_common.cpp
@@ -13,7 +13,7 @@
#include <cstring>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_common)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const uint16_t random_u16 = fuzzed_data_provider.ConsumeIntegral<uint16_t>();
diff --git a/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp b/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
index e0a4e90c10..8cb9c55283 100644
--- a/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
+++ b/src/test/fuzz/crypto_hkdf_hmac_sha256_l32.cpp
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_hkdf_hmac_sha256_l32)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/crypto_poly1305.cpp b/src/test/fuzz/crypto_poly1305.cpp
index 5681e6a693..ac555ed68c 100644
--- a/src/test/fuzz/crypto_poly1305.cpp
+++ b/src/test/fuzz/crypto_poly1305.cpp
@@ -10,7 +10,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(crypto_poly1305)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
diff --git a/src/test/fuzz/cuckoocache.cpp b/src/test/fuzz/cuckoocache.cpp
index 5b45aa79d8..dc20dc3f62 100644
--- a/src/test/fuzz/cuckoocache.cpp
+++ b/src/test/fuzz/cuckoocache.cpp
@@ -26,7 +26,7 @@ struct RandomHasher {
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(cuckoocache)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
fuzzed_data_provider_ptr = &fuzzed_data_provider;
diff --git a/src/test/fuzz/danger_link_all.sh b/src/test/fuzz/danger_link_all.sh
new file mode 100755
index 0000000000..2ddd00c658
--- /dev/null
+++ b/src/test/fuzz/danger_link_all.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+# 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.
+
+export LC_ALL=C.UTF-8
+
+set -e
+
+ROOT_DIR="$(git rev-parse --show-toplevel)"
+
+# Run only once (break make recursion)
+if [ -d "${ROOT_DIR}/lock_fuzz_link_all" ]; then
+ exit
+fi
+mkdir "${ROOT_DIR}/lock_fuzz_link_all"
+
+echo "Linking each fuzz target separately."
+for FUZZING_HARNESS in $(PRINT_ALL_FUZZ_TARGETS_AND_ABORT=1 "${ROOT_DIR}/src/test/fuzz/fuzz" | sort -u); do
+ echo "Building src/test/fuzz/${FUZZING_HARNESS} ..."
+ git checkout -- "${ROOT_DIR}/src/test/fuzz/fuzz.cpp"
+ sed -i "s/std::getenv(\"FUZZ\")/\"${FUZZING_HARNESS}\"/g" "${ROOT_DIR}/src/test/fuzz/fuzz.cpp"
+ make
+ mv "${ROOT_DIR}/src/test/fuzz/fuzz" "${ROOT_DIR}/src/test/fuzz/${FUZZING_HARNESS}"
+done
+git checkout -- "${ROOT_DIR}/src/test/fuzz/fuzz.cpp"
+rmdir "${ROOT_DIR}/lock_fuzz_link_all"
+echo "Successfully built all fuzz targets."
diff --git a/src/test/fuzz/decode_tx.cpp b/src/test/fuzz/decode_tx.cpp
index 0d89d4228a..249f5a3cda 100644
--- a/src/test/fuzz/decode_tx.cpp
+++ b/src/test/fuzz/decode_tx.cpp
@@ -12,20 +12,21 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(decode_tx)
{
const std::string tx_hex = HexStr(buffer);
CMutableTransaction mtx;
const bool result_none = DecodeHexTx(mtx, tx_hex, false, false);
const bool result_try_witness = DecodeHexTx(mtx, tx_hex, false, true);
const bool result_try_witness_and_maybe_no_witness = DecodeHexTx(mtx, tx_hex, true, true);
- const bool result_try_no_witness = DecodeHexTx(mtx, tx_hex, true, false);
+ CMutableTransaction no_witness_mtx;
+ const bool result_try_no_witness = DecodeHexTx(no_witness_mtx, tx_hex, true, false);
assert(!result_none);
if (result_try_witness_and_maybe_no_witness) {
assert(result_try_no_witness || result_try_witness);
}
- // if (result_try_no_witness) { // Uncomment when https://github.com/bitcoin/bitcoin/pull/17775 is merged
- if (result_try_witness) { // Remove stop-gap when https://github.com/bitcoin/bitcoin/pull/17775 is merged
+ if (result_try_no_witness) {
+ assert(!no_witness_mtx.HasWitness());
assert(result_try_witness_and_maybe_no_witness);
}
}
diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp
index 001758ffdb..0d1921f285 100644
--- a/src/test/fuzz/descriptor_parse.cpp
+++ b/src/test/fuzz/descriptor_parse.cpp
@@ -8,13 +8,14 @@
#include <test/fuzz/fuzz.h>
#include <util/memory.h>
-void initialize()
+void initialize_descriptor_parse()
{
static const ECCVerifyHandle verify_handle;
- SelectParams(CBaseChainParams::REGTEST);
+ ECC_Start();
+ SelectParams(CBaseChainParams::MAIN);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(descriptor_parse, initialize_descriptor_parse)
{
const std::string descriptor(buffer.begin(), buffer.end());
FlatSigningProvider signing_provider;
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index b799d3b43b..74dec6475e 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -13,7 +13,9 @@
#include <key.h>
#include <merkleblock.h>
#include <net.h>
+#include <netbase.h>
#include <node/utxo_snapshot.h>
+#include <optional.h>
#include <primitives/block.h>
#include <protocol.h>
#include <psbt.h>
@@ -32,21 +34,30 @@
#include <test/fuzz/fuzz.h>
-void initialize()
+void initialize_deserialize()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
static const ECCVerifyHandle verify_handle;
}
+#define FUZZ_TARGET_DESERIALIZE(name, code) \
+ FUZZ_TARGET_INIT(name, initialize_deserialize) \
+ { \
+ try { \
+ code \
+ } catch (const invalid_fuzzing_input_exception&) { \
+ } \
+ }
+
namespace {
struct invalid_fuzzing_input_exception : public std::exception {
};
template <typename T>
-CDataStream Serialize(const T& obj)
+CDataStream Serialize(const T& obj, const int version = INIT_PROTO_VERSION)
{
- CDataStream ds(SER_NETWORK, INIT_PROTO_VERSION);
+ CDataStream ds(SER_NETWORK, version);
ds << obj;
return ds;
}
@@ -60,15 +71,19 @@ T Deserialize(CDataStream ds)
}
template <typename T>
-void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj)
+void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj, const Optional<int> protocol_version = nullopt)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
- try {
- int version;
- ds >> version;
- ds.SetVersion(version);
- } catch (const std::ios_base::failure&) {
- throw invalid_fuzzing_input_exception();
+ if (protocol_version) {
+ ds.SetVersion(*protocol_version);
+ } else {
+ try {
+ int version;
+ ds >> version;
+ ds.SetVersion(version);
+ } catch (const std::ios_base::failure&) {
+ throw invalid_fuzzing_input_exception();
+ }
}
try {
ds >> obj;
@@ -79,159 +94,209 @@ void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj)
}
template <typename T>
-void AssertEqualAfterSerializeDeserialize(const T& obj)
+void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT_PROTO_VERSION)
{
- assert(Deserialize<T>(Serialize(obj)) == obj);
+ assert(Deserialize<T>(Serialize(obj, version)) == obj);
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
-{
- try {
-#if BLOCK_FILTER_DESERIALIZE
+FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, {
BlockFilter block_filter;
DeserializeFromFuzzingInput(buffer, block_filter);
-#elif ADDR_INFO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(addr_info_deserialize, {
CAddrInfo addr_info;
DeserializeFromFuzzingInput(buffer, addr_info);
-#elif BLOCK_FILE_INFO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, {
CBlockFileInfo block_file_info;
DeserializeFromFuzzingInput(buffer, block_file_info);
-#elif BLOCK_HEADER_AND_SHORT_TXIDS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, {
CBlockHeaderAndShortTxIDs block_header_and_short_txids;
DeserializeFromFuzzingInput(buffer, block_header_and_short_txids);
-#elif FEE_RATE_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, {
CFeeRate fee_rate;
DeserializeFromFuzzingInput(buffer, fee_rate);
AssertEqualAfterSerializeDeserialize(fee_rate);
-#elif MERKLE_BLOCK_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, {
CMerkleBlock merkle_block;
DeserializeFromFuzzingInput(buffer, merkle_block);
-#elif OUT_POINT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(out_point_deserialize, {
COutPoint out_point;
DeserializeFromFuzzingInput(buffer, out_point);
AssertEqualAfterSerializeDeserialize(out_point);
-#elif PARTIAL_MERKLE_TREE_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, {
CPartialMerkleTree partial_merkle_tree;
DeserializeFromFuzzingInput(buffer, partial_merkle_tree);
-#elif PUB_KEY_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, {
CPubKey pub_key;
DeserializeFromFuzzingInput(buffer, pub_key);
// TODO: The following equivalence should hold for CPubKey? Fix.
// AssertEqualAfterSerializeDeserialize(pub_key);
-#elif SCRIPT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(script_deserialize, {
CScript script;
DeserializeFromFuzzingInput(buffer, script);
-#elif SUB_NET_DESERIALIZE
- CSubNet sub_net;
- DeserializeFromFuzzingInput(buffer, sub_net);
- AssertEqualAfterSerializeDeserialize(sub_net);
-#elif TX_IN_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(sub_net_deserialize, {
+ CSubNet sub_net_1;
+ DeserializeFromFuzzingInput(buffer, sub_net_1, INIT_PROTO_VERSION);
+ AssertEqualAfterSerializeDeserialize(sub_net_1, INIT_PROTO_VERSION);
+ CSubNet sub_net_2;
+ DeserializeFromFuzzingInput(buffer, sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT);
+ AssertEqualAfterSerializeDeserialize(sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT);
+ CSubNet sub_net_3;
+ DeserializeFromFuzzingInput(buffer, sub_net_3);
+ AssertEqualAfterSerializeDeserialize(sub_net_3, INIT_PROTO_VERSION | ADDRV2_FORMAT);
+})
+FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, {
CTxIn tx_in;
DeserializeFromFuzzingInput(buffer, tx_in);
AssertEqualAfterSerializeDeserialize(tx_in);
-#elif FLAT_FILE_POS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, {
FlatFilePos flat_file_pos;
DeserializeFromFuzzingInput(buffer, flat_file_pos);
AssertEqualAfterSerializeDeserialize(flat_file_pos);
-#elif KEY_ORIGIN_INFO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, {
KeyOriginInfo key_origin_info;
DeserializeFromFuzzingInput(buffer, key_origin_info);
AssertEqualAfterSerializeDeserialize(key_origin_info);
-#elif PARTIALLY_SIGNED_TRANSACTION_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, {
PartiallySignedTransaction partially_signed_transaction;
DeserializeFromFuzzingInput(buffer, partially_signed_transaction);
-#elif PREFILLED_TRANSACTION_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, {
PrefilledTransaction prefilled_transaction;
DeserializeFromFuzzingInput(buffer, prefilled_transaction);
-#elif PSBT_INPUT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, {
PSBTInput psbt_input;
DeserializeFromFuzzingInput(buffer, psbt_input);
-#elif PSBT_OUTPUT_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, {
PSBTOutput psbt_output;
DeserializeFromFuzzingInput(buffer, psbt_output);
-#elif BLOCK_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(block_deserialize, {
CBlock block;
DeserializeFromFuzzingInput(buffer, block);
-#elif BLOCKLOCATOR_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, {
CBlockLocator bl;
DeserializeFromFuzzingInput(buffer, bl);
-#elif BLOCKMERKLEROOT
+})
+FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
CBlock block;
DeserializeFromFuzzingInput(buffer, block);
bool mutated;
BlockMerkleRoot(block, &mutated);
-#elif ADDRMAN_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(addrman_deserialize, {
CAddrMan am;
DeserializeFromFuzzingInput(buffer, am);
-#elif BLOCKHEADER_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
CBlockHeader bh;
DeserializeFromFuzzingInput(buffer, bh);
-#elif BANENTRY_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(banentry_deserialize, {
CBanEntry be;
DeserializeFromFuzzingInput(buffer, be);
-#elif TXUNDO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(txundo_deserialize, {
CTxUndo tu;
DeserializeFromFuzzingInput(buffer, tu);
-#elif BLOCKUNDO_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, {
CBlockUndo bu;
DeserializeFromFuzzingInput(buffer, bu);
-#elif COINS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(coins_deserialize, {
Coin coin;
DeserializeFromFuzzingInput(buffer, coin);
-#elif NETADDR_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(netaddr_deserialize, {
CNetAddr na;
DeserializeFromFuzzingInput(buffer, na);
- AssertEqualAfterSerializeDeserialize(na);
-#elif SERVICE_DESERIALIZE
+ if (na.IsAddrV1Compatible()) {
+ AssertEqualAfterSerializeDeserialize(na);
+ }
+ AssertEqualAfterSerializeDeserialize(na, INIT_PROTO_VERSION | ADDRV2_FORMAT);
+})
+FUZZ_TARGET_DESERIALIZE(service_deserialize, {
CService s;
DeserializeFromFuzzingInput(buffer, s);
- AssertEqualAfterSerializeDeserialize(s);
-#elif MESSAGEHEADER_DESERIALIZE
+ if (s.IsAddrV1Compatible()) {
+ AssertEqualAfterSerializeDeserialize(s);
+ }
+ AssertEqualAfterSerializeDeserialize(s, INIT_PROTO_VERSION | ADDRV2_FORMAT);
+ CService s1;
+ DeserializeFromFuzzingInput(buffer, s1, INIT_PROTO_VERSION);
+ AssertEqualAfterSerializeDeserialize(s1, INIT_PROTO_VERSION);
+ assert(s1.IsAddrV1Compatible());
+ CService s2;
+ DeserializeFromFuzzingInput(buffer, s2, INIT_PROTO_VERSION | ADDRV2_FORMAT);
+ AssertEqualAfterSerializeDeserialize(s2, INIT_PROTO_VERSION | ADDRV2_FORMAT);
+})
+FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, {
CMessageHeader mh;
DeserializeFromFuzzingInput(buffer, mh);
(void)mh.IsCommandValid();
-#elif ADDRESS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(address_deserialize, {
CAddress a;
DeserializeFromFuzzingInput(buffer, a);
-#elif INV_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(inv_deserialize, {
CInv i;
DeserializeFromFuzzingInput(buffer, i);
-#elif BLOOMFILTER_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, {
CBloomFilter bf;
DeserializeFromFuzzingInput(buffer, bf);
-#elif DISKBLOCKINDEX_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, {
CDiskBlockIndex dbi;
DeserializeFromFuzzingInput(buffer, dbi);
-#elif TXOUTCOMPRESSOR_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, {
CTxOut to;
auto toc = Using<TxOutCompression>(to);
DeserializeFromFuzzingInput(buffer, toc);
-#elif BLOCKTRANSACTIONS_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, {
BlockTransactions bt;
DeserializeFromFuzzingInput(buffer, bt);
-#elif BLOCKTRANSACTIONSREQUEST_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, {
BlockTransactionsRequest btr;
DeserializeFromFuzzingInput(buffer, btr);
-#elif SNAPSHOTMETADATA_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, {
SnapshotMetadata snapshot_metadata;
DeserializeFromFuzzingInput(buffer, snapshot_metadata);
-#elif UINT160_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(uint160_deserialize, {
uint160 u160;
DeserializeFromFuzzingInput(buffer, u160);
AssertEqualAfterSerializeDeserialize(u160);
-#elif UINT256_DESERIALIZE
+})
+FUZZ_TARGET_DESERIALIZE(uint256_deserialize, {
uint256 u256;
DeserializeFromFuzzingInput(buffer, u256);
AssertEqualAfterSerializeDeserialize(u256);
-#else
-#error Need at least one fuzz target to compile
-#endif
+})
// Classes intentionally not covered in this file since their deserialization code is
// fuzzed elsewhere:
// * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp
// * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp
- } catch (const invalid_fuzzing_input_exception&) {
- }
-}
diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp
index c556599db3..635288fc36 100644
--- a/src/test/fuzz/eval_script.cpp
+++ b/src/test/fuzz/eval_script.cpp
@@ -10,12 +10,12 @@
#include <limits>
-void initialize()
+void initialize_eval_script()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(eval_script, initialize_eval_script)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
diff --git a/src/test/fuzz/fee_rate.cpp b/src/test/fuzz/fee_rate.cpp
index f3d44d9f93..2955213635 100644
--- a/src/test/fuzz/fee_rate.cpp
+++ b/src/test/fuzz/fee_rate.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(fee_rate)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CAmount satoshis_per_k = ConsumeMoney(fuzzed_data_provider);
diff --git a/src/test/fuzz/fees.cpp b/src/test/fuzz/fees.cpp
index ce8700befa..61c7681bf9 100644
--- a/src/test/fuzz/fees.cpp
+++ b/src/test/fuzz/fees.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(fees)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CFeeRate minimal_incremental_fee{ConsumeMoney(fuzzed_data_provider)};
diff --git a/src/test/fuzz/flatfile.cpp b/src/test/fuzz/flatfile.cpp
index 95dabb8bab..d142e374b1 100644
--- a/src/test/fuzz/flatfile.cpp
+++ b/src/test/fuzz/flatfile.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(flatfile)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
std::optional<FlatFilePos> flat_file_pos = ConsumeDeserializable<FlatFilePos>(fuzzed_data_provider);
diff --git a/src/test/fuzz/float.cpp b/src/test/fuzz/float.cpp
index a24bae5b35..d18a87d177 100644
--- a/src/test/fuzz/float.cpp
+++ b/src/test/fuzz/float.cpp
@@ -12,7 +12,7 @@
#include <cassert>
#include <cstdint>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(float)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp
index 753cfffdcb..fd87667755 100644
--- a/src/test/fuzz/fuzz.cpp
+++ b/src/test/fuzz/fuzz.cpp
@@ -5,6 +5,7 @@
#include <test/fuzz/fuzz.h>
#include <test/util/setup_common.h>
+#include <util/check.h>
#include <cstdint>
#include <unistd.h>
@@ -12,6 +13,36 @@
const std::function<void(const std::string&)> G_TEST_LOG_FUN{};
+std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize>>& FuzzTargets()
+{
+ static std::map<std::string_view, std::tuple<TypeTestOneInput, TypeInitialize>> g_fuzz_targets;
+ return g_fuzz_targets;
+}
+
+void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init)
+{
+ const auto it_ins = FuzzTargets().try_emplace(name, std::move(target), std::move(init));
+ Assert(it_ins.second);
+}
+
+static TypeTestOneInput* g_test_one_input{nullptr};
+
+void initialize()
+{
+ if (std::getenv("PRINT_ALL_FUZZ_TARGETS_AND_ABORT")) {
+ for (const auto& t : FuzzTargets()) {
+ std::cout << t.first << std::endl;
+ }
+ Assert(false);
+ }
+ std::string_view fuzz_target{Assert(std::getenv("FUZZ"))};
+ const auto it = FuzzTargets().find(fuzz_target);
+ Assert(it != FuzzTargets().end());
+ Assert(!g_test_one_input);
+ g_test_one_input = &std::get<0>(it->second);
+ std::get<1>(it->second)();
+}
+
#if defined(PROVIDE_MAIN_FUNCTION)
static bool read_stdin(std::vector<uint8_t>& data)
{
@@ -24,14 +55,10 @@ static bool read_stdin(std::vector<uint8_t>& data)
}
#endif
-// Default initialization: Override using a non-weak initialize().
-__attribute__((weak)) void initialize()
-{
-}
-
// This function is used by libFuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
+ static const auto& test_one_input = *Assert(g_test_one_input);
const std::vector<uint8_t> input(data, data + size);
test_one_input(input);
return 0;
@@ -48,6 +75,7 @@ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv)
__attribute__((weak)) int main(int argc, char** argv)
{
initialize();
+ static const auto& test_one_input = *Assert(g_test_one_input);
#ifdef __AFL_INIT
// Enable AFL deferred forkserver mode. Requires compilation using
// afl-clang-fast++. See fuzzing.md for details.
diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h
index 3be202b16e..544379c0b0 100644
--- a/src/test/fuzz/fuzz.h
+++ b/src/test/fuzz/fuzz.h
@@ -5,10 +5,29 @@
#ifndef BITCOIN_TEST_FUZZ_FUZZ_H
#define BITCOIN_TEST_FUZZ_FUZZ_H
-#include <stdint.h>
+#include <cstdint>
+#include <functional>
+#include <string_view>
#include <vector>
-void initialize();
-void test_one_input(const std::vector<uint8_t>& buffer);
+using TypeTestOneInput = std::function<void(const std::vector<uint8_t>&)>;
+using TypeInitialize = std::function<void()>;
+
+void FuzzFrameworkRegisterTarget(std::string_view name, TypeTestOneInput target, TypeInitialize init);
+
+void FuzzFrameworkEmptyFun() {}
+
+#define FUZZ_TARGET(name) \
+ FUZZ_TARGET_INIT(name, FuzzFrameworkEmptyFun)
+
+#define FUZZ_TARGET_INIT(name, init_fun) \
+ void name##_fuzz_target(const std::vector<uint8_t>&); \
+ struct name##_Before_Main { \
+ name##_Before_Main() \
+ { \
+ FuzzFrameworkRegisterTarget(#name, name##_fuzz_target, init_fun); \
+ } \
+ } const static g_##name##_before_main; \
+ void name##_fuzz_target(const std::vector<uint8_t>& buffer)
#endif // BITCOIN_TEST_FUZZ_FUZZ_H
diff --git a/src/test/fuzz/golomb_rice.cpp b/src/test/fuzz/golomb_rice.cpp
index a9f450b0c4..c99bf940c7 100644
--- a/src/test/fuzz/golomb_rice.cpp
+++ b/src/test/fuzz/golomb_rice.cpp
@@ -54,7 +54,7 @@ std::vector<uint64_t> BuildHashedSet(const std::unordered_set<std::vector<uint8_
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(golomb_rice)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
std::vector<uint8_t> golomb_rice_data;
diff --git a/src/test/fuzz/hex.cpp b/src/test/fuzz/hex.cpp
index 6a8699fd0f..cc1bc1c8cf 100644
--- a/src/test/fuzz/hex.cpp
+++ b/src/test/fuzz/hex.cpp
@@ -16,12 +16,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_hex()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(hex, initialize_hex)
{
const std::string random_hex_string(buffer.begin(), buffer.end());
const std::vector<unsigned char> data = ParseHex(random_hex_string);
diff --git a/src/test/fuzz/http_request.cpp b/src/test/fuzz/http_request.cpp
index 36d44e361f..e3b62032bc 100644
--- a/src/test/fuzz/http_request.cpp
+++ b/src/test/fuzz/http_request.cpp
@@ -39,7 +39,7 @@ extern "C" int evhttp_parse_headers_(struct evhttp_request*, struct evbuffer*);
std::string RequestMethodString(HTTPRequest::RequestMethod m);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(http_request)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
evhttp_request* evreq = evhttp_request_new(nullptr, nullptr);
diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp
index 35d6804d4f..ac83d91ea0 100644
--- a/src/test/fuzz/integer.cpp
+++ b/src/test/fuzz/integer.cpp
@@ -40,12 +40,12 @@
#include <set>
#include <vector>
-void initialize()
+void initialize_integer()
{
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(integer, initialize_integer)
{
if (buffer.size() < sizeof(uint256) + sizeof(uint160)) {
return;
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index 955b954700..aa8f826e4a 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -26,14 +26,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_key()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(key, initialize_key)
{
const CKey key = [&] {
CKey k;
diff --git a/src/test/fuzz/key_io.cpp b/src/test/fuzz/key_io.cpp
index 62aefb650d..665ca01fa1 100644
--- a/src/test/fuzz/key_io.cpp
+++ b/src/test/fuzz/key_io.cpp
@@ -14,14 +14,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_key_io()
{
static const ECCVerifyHandle verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::MAIN);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(key_io, initialize_key_io)
{
const std::string random_string(buffer.begin(), buffer.end());
diff --git a/src/test/fuzz/kitchen_sink.cpp b/src/test/fuzz/kitchen_sink.cpp
index 82cbc00a3a..0656ddc547 100644
--- a/src/test/fuzz/kitchen_sink.cpp
+++ b/src/test/fuzz/kitchen_sink.cpp
@@ -15,7 +15,7 @@
// The fuzzing kitchen sink: Fuzzing harness for functions that need to be
// fuzzed but a.) don't belong in any existing fuzzing harness file, and
// b.) are not important enough to warrant their own fuzzing harness file.
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(kitchen_sink)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/load_external_block_file.cpp b/src/test/fuzz/load_external_block_file.cpp
index d9de9d9866..c428a86631 100644
--- a/src/test/fuzz/load_external_block_file.cpp
+++ b/src/test/fuzz/load_external_block_file.cpp
@@ -13,12 +13,12 @@
#include <cstdint>
#include <vector>
-void initialize()
+void initialize_load_external_block_file()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
FuzzedFileProvider fuzzed_file_provider = ConsumeFile(fuzzed_data_provider);
diff --git a/src/test/fuzz/locale.cpp b/src/test/fuzz/locale.cpp
index 2b181c6da1..5b1acae57b 100644
--- a/src/test/fuzz/locale.cpp
+++ b/src/test/fuzz/locale.cpp
@@ -35,7 +35,7 @@ bool IsAvailableLocale(const std::string& locale_identifier)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(locale)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string locale_identifier = ConsumeLocaleIdentifier(fuzzed_data_provider);
diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp
index c44e334272..15bcfab3ad 100644
--- a/src/test/fuzz/merkleblock.cpp
+++ b/src/test/fuzz/merkleblock.cpp
@@ -13,15 +13,39 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(merkleblock)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- std::optional<CPartialMerkleTree> partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider);
- if (!partial_merkle_tree) {
- return;
+ CPartialMerkleTree partial_merkle_tree;
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1)) {
+ case 0: {
+ const std::optional<CPartialMerkleTree> opt_partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider);
+ if (opt_partial_merkle_tree) {
+ partial_merkle_tree = *opt_partial_merkle_tree;
+ }
+ break;
}
- (void)partial_merkle_tree->GetNumTransactions();
+ case 1: {
+ CMerkleBlock merkle_block;
+ const std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
+ CBloomFilter bloom_filter;
+ std::set<uint256> txids;
+ if (opt_block && !opt_block->vtx.empty()) {
+ if (fuzzed_data_provider.ConsumeBool()) {
+ merkle_block = CMerkleBlock{*opt_block, bloom_filter};
+ } else if (fuzzed_data_provider.ConsumeBool()) {
+ while (fuzzed_data_provider.ConsumeBool()) {
+ txids.insert(ConsumeUInt256(fuzzed_data_provider));
+ }
+ merkle_block = CMerkleBlock{*opt_block, txids};
+ }
+ }
+ partial_merkle_tree = merkle_block.txn;
+ break;
+ }
+ }
+ (void)partial_merkle_tree.GetNumTransactions();
std::vector<uint256> matches;
std::vector<unsigned int> indices;
- (void)partial_merkle_tree->ExtractMatches(matches, indices);
+ (void)partial_merkle_tree.ExtractMatches(matches, indices);
}
diff --git a/src/test/fuzz/message.cpp b/src/test/fuzz/message.cpp
index fa0322a391..06cd0afe2a 100644
--- a/src/test/fuzz/message.cpp
+++ b/src/test/fuzz/message.cpp
@@ -16,14 +16,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_message()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(message, initialize_message)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string random_message = fuzzed_data_provider.ConsumeRandomLengthString(1024);
diff --git a/src/test/fuzz/multiplication_overflow.cpp b/src/test/fuzz/multiplication_overflow.cpp
index a4b158c18b..0f054529a6 100644
--- a/src/test/fuzz/multiplication_overflow.cpp
+++ b/src/test/fuzz/multiplication_overflow.cpp
@@ -14,7 +14,7 @@
#if __has_builtin(__builtin_mul_overflow)
#define HAVE_BUILTIN_MUL_OVERFLOW
#endif
-#elif defined(__GNUC__) && (__GNUC__ >= 5)
+#elif defined(__GNUC__)
#define HAVE_BUILTIN_MUL_OVERFLOW
#endif
@@ -40,7 +40,7 @@ void TestMultiplicationOverflow(FuzzedDataProvider& fuzzed_data_provider)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(multiplication_overflow)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
TestMultiplicationOverflow<int64_t>(fuzzed_data_provider);
diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp
index 3818838765..66d7c512e4 100644
--- a/src/test/fuzz/net.cpp
+++ b/src/test/fuzz/net.cpp
@@ -19,15 +19,15 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_net()
{
static const BasicTestingSetup basic_testing_setup;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(net, initialize_net)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
-
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
const std::optional<CAddress> address = ConsumeDeserializable<CAddress>(fuzzed_data_provider);
if (!address) {
return;
@@ -48,8 +48,9 @@ void test_one_input(const std::vector<uint8_t>& buffer)
fuzzed_data_provider.ConsumeRandomLengthString(32),
fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH}),
fuzzed_data_provider.ConsumeBool()};
+ node.SetCommonVersion(fuzzed_data_provider.ConsumeIntegral<int>());
while (fuzzed_data_provider.ConsumeBool()) {
- switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 11)) {
+ switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 10)) {
case 0: {
node.CloseSocketDisconnect();
break;
@@ -59,11 +60,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
break;
}
case 2: {
- node.SetCommonVersion(fuzzed_data_provider.ConsumeIntegral<int>());
- break;
- }
- case 3: {
- const std::vector<bool> asmap = ConsumeRandomLengthIntegralVector<bool>(fuzzed_data_provider, 128);
+ const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider);
if (!SanityCheckASMap(asmap)) {
break;
}
@@ -71,18 +68,18 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.copyStats(stats, asmap);
break;
}
- case 4: {
+ case 3: {
const CNode* add_ref_node = node.AddRef();
assert(add_ref_node == &node);
break;
}
- case 5: {
+ case 4: {
if (node.GetRefCount() > 0) {
node.Release();
}
break;
}
- case 6: {
+ case 5: {
if (node.m_addr_known == nullptr) {
break;
}
@@ -93,7 +90,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.AddAddressKnown(*addr_opt);
break;
}
- case 7: {
+ case 6: {
if (node.m_addr_known == nullptr) {
break;
}
@@ -105,7 +102,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.PushAddress(*addr_opt, fast_random_context);
break;
}
- case 8: {
+ case 7: {
const std::optional<CInv> inv_opt = ConsumeDeserializable<CInv>(fuzzed_data_provider);
if (!inv_opt) {
break;
@@ -113,11 +110,11 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.AddKnownTx(inv_opt->hash);
break;
}
- case 9: {
+ case 8: {
node.PushTxInventory(ConsumeUInt256(fuzzed_data_provider));
break;
}
- case 10: {
+ case 9: {
const std::optional<CService> service_opt = ConsumeDeserializable<CService>(fuzzed_data_provider);
if (!service_opt) {
break;
@@ -125,10 +122,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
node.SetAddrLocal(*service_opt);
break;
}
- case 11: {
+ case 10: {
const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
bool complete;
- node.ReceiveMsgBytes((const char*)b.data(), b.size(), complete);
+ node.ReceiveMsgBytes(b, complete);
break;
}
}
diff --git a/src/test/fuzz/net_permissions.cpp b/src/test/fuzz/net_permissions.cpp
index 8a674ac1e9..3620e16d30 100644
--- a/src/test/fuzz/net_permissions.cpp
+++ b/src/test/fuzz/net_permissions.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(net_permissions)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(32);
diff --git a/src/test/fuzz/netaddress.cpp b/src/test/fuzz/netaddress.cpp
index 8252f38726..6e9bb47ff6 100644
--- a/src/test/fuzz/netaddress.cpp
+++ b/src/test/fuzz/netaddress.cpp
@@ -12,7 +12,7 @@
#include <netinet/in.h>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(netaddress)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/p2p_transport_deserializer.cpp b/src/test/fuzz/p2p_transport_deserializer.cpp
index 7e216e16fe..6ba75309c8 100644
--- a/src/test/fuzz/p2p_transport_deserializer.cpp
+++ b/src/test/fuzz/p2p_transport_deserializer.cpp
@@ -12,24 +12,21 @@
#include <limits>
#include <vector>
-void initialize()
+void initialize_p2p_transport_deserializer()
{
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(p2p_transport_deserializer, initialize_p2p_transport_deserializer)
{
// Construct deserializer, with a dummy NodeId
V1TransportDeserializer deserializer{Params(), (NodeId)0, SER_NETWORK, INIT_PROTO_VERSION};
- const char* pch = (const char*)buffer.data();
- size_t n_bytes = buffer.size();
- while (n_bytes > 0) {
- const int handled = deserializer.Read(pch, n_bytes);
+ Span<const uint8_t> msg_bytes{buffer};
+ while (msg_bytes.size() > 0) {
+ const int handled = deserializer.Read(msg_bytes);
if (handled < 0) {
break;
}
- pch += handled;
- n_bytes -= handled;
if (deserializer.Complete()) {
const std::chrono::microseconds m_time{std::numeric_limits<int64_t>::max()};
uint32_t out_err_raw_size{0};
diff --git a/src/test/fuzz/parse_hd_keypath.cpp b/src/test/fuzz/parse_hd_keypath.cpp
index f668ca8c48..7d0d5643bf 100644
--- a/src/test/fuzz/parse_hd_keypath.cpp
+++ b/src/test/fuzz/parse_hd_keypath.cpp
@@ -10,7 +10,7 @@
#include <cstdint>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_hd_keypath)
{
const std::string keypath_str(buffer.begin(), buffer.end());
std::vector<uint32_t> keypath;
diff --git a/src/test/fuzz/parse_iso8601.cpp b/src/test/fuzz/parse_iso8601.cpp
index c86f8a853e..4d5fa70dfa 100644
--- a/src/test/fuzz/parse_iso8601.cpp
+++ b/src/test/fuzz/parse_iso8601.cpp
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_iso8601)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/parse_numbers.cpp b/src/test/fuzz/parse_numbers.cpp
index 59f89dc9fb..89d9be392e 100644
--- a/src/test/fuzz/parse_numbers.cpp
+++ b/src/test/fuzz/parse_numbers.cpp
@@ -8,7 +8,7 @@
#include <string>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_numbers)
{
const std::string random_string(buffer.begin(), buffer.end());
diff --git a/src/test/fuzz/parse_script.cpp b/src/test/fuzz/parse_script.cpp
index 21ac1aecf3..1382afbc2c 100644
--- a/src/test/fuzz/parse_script.cpp
+++ b/src/test/fuzz/parse_script.cpp
@@ -6,7 +6,7 @@
#include <script/script.h>
#include <test/fuzz/fuzz.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(parse_script)
{
const std::string script_string(buffer.begin(), buffer.end());
try {
diff --git a/src/test/fuzz/parse_univalue.cpp b/src/test/fuzz/parse_univalue.cpp
index a269378607..afe382ba21 100644
--- a/src/test/fuzz/parse_univalue.cpp
+++ b/src/test/fuzz/parse_univalue.cpp
@@ -12,13 +12,13 @@
#include <limits>
#include <string>
-void initialize()
+void initialize_parse_univalue()
{
static const ECCVerifyHandle verify_handle;
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(parse_univalue, initialize_parse_univalue)
{
const std::string random_string(buffer.begin(), buffer.end());
bool valid = true;
diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp
index 6c94a47f3c..8a17a4b51b 100644
--- a/src/test/fuzz/policy_estimator.cpp
+++ b/src/test/fuzz/policy_estimator.cpp
@@ -14,12 +14,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_policy_estimator()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
CBlockPolicyEstimator block_policy_estimator;
diff --git a/src/test/fuzz/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp
index 0edcf201c7..8fa52143d8 100644
--- a/src/test/fuzz/policy_estimator_io.cpp
+++ b/src/test/fuzz/policy_estimator_io.cpp
@@ -10,12 +10,12 @@
#include <cstdint>
#include <vector>
-void initialize()
+void initialize_policy_estimator_io()
{
InitializeFuzzingContext();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+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);
diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp
index b7fc72373d..02beb6eb37 100644
--- a/src/test/fuzz/pow.cpp
+++ b/src/test/fuzz/pow.cpp
@@ -15,12 +15,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_pow()
{
SelectParams(CBaseChainParams::MAIN);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(pow, initialize_pow)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const Consensus::Params& consensus_params = Params().GetConsensus();
diff --git a/src/test/fuzz/prevector.cpp b/src/test/fuzz/prevector.cpp
index 626e187cbd..51956bbe9e 100644
--- a/src/test/fuzz/prevector.cpp
+++ b/src/test/fuzz/prevector.cpp
@@ -204,7 +204,7 @@ public:
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(prevector)
{
FuzzedDataProvider prov(buffer.data(), buffer.size());
prevector_tester<8, int> test;
diff --git a/src/test/fuzz/primitives_transaction.cpp b/src/test/fuzz/primitives_transaction.cpp
index 4a0f920f58..48815c8910 100644
--- a/src/test/fuzz/primitives_transaction.cpp
+++ b/src/test/fuzz/primitives_transaction.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(primitives_transaction)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const CScript script = ConsumeScript(fuzzed_data_provider);
diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp
index 3ef03137ec..01de8bdbb5 100644
--- a/src/test/fuzz/process_message.cpp
+++ b/src/test/fuzz/process_message.cpp
@@ -16,6 +16,7 @@
#include <test/util/mining.h>
#include <test/util/net.h>
#include <test/util/setup_common.h>
+#include <test/util/validation.h>
#include <util/memory.h>
#include <validationinterface.h>
#include <version.h>
@@ -31,19 +32,10 @@
#include <vector>
namespace {
-
-#ifdef MESSAGE_TYPE
-#define TO_STRING_(s) #s
-#define TO_STRING(s) TO_STRING_(s)
-const std::string LIMIT_TO_MESSAGE_TYPE{TO_STRING(MESSAGE_TYPE)};
-#else
-const std::string LIMIT_TO_MESSAGE_TYPE;
-#endif
-
const TestingSetup* g_setup;
} // namespace
-void initialize()
+void initialize_process_message()
{
static TestingSetup setup{
CBaseChainParams::REGTEST,
@@ -59,14 +51,18 @@ void initialize()
SyncWithValidationInterfaceQueue();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+void fuzz_target(const std::vector<uint8_t>& buffer, const std::string& LIMIT_TO_MESSAGE_TYPE)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
+ TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate();
+ chainstate.ResetIbd();
const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()};
if (!LIMIT_TO_MESSAGE_TYPE.empty() && random_message_type != LIMIT_TO_MESSAGE_TYPE) {
return;
}
+ const bool jump_out_of_ibd{fuzzed_data_provider.ConsumeBool()};
+ if (jump_out_of_ibd) chainstate.JumpOutOfIbd();
CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes<unsigned char>(), SER_NETWORK, PROTOCOL_VERSION};
CNode& p2p_node = *MakeUnique<CNode>(0, ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, ConnectionType::OUTBOUND_FULL_RELAY).release();
p2p_node.fSuccessfullyConnected = true;
@@ -76,10 +72,36 @@ void test_one_input(const std::vector<uint8_t>& buffer)
g_setup->m_node.peerman->InitializeNode(&p2p_node);
try {
g_setup->m_node.peerman->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream,
- GetTime<std::chrono::microseconds>(), std::atomic<bool>{false});
+ GetTime<std::chrono::microseconds>(), std::atomic<bool>{false});
} catch (const std::ios_base::failure&) {
}
SyncWithValidationInterfaceQueue();
LOCK2(::cs_main, g_cs_orphans); // See init.cpp for rationale for implicit locking order requirement
g_setup->m_node.connman->StopNodes();
}
+
+FUZZ_TARGET_INIT(process_message, initialize_process_message) { fuzz_target(buffer, ""); }
+FUZZ_TARGET_INIT(process_message_addr, initialize_process_message) { fuzz_target(buffer, "addr"); }
+FUZZ_TARGET_INIT(process_message_block, initialize_process_message) { fuzz_target(buffer, "block"); }
+FUZZ_TARGET_INIT(process_message_blocktxn, initialize_process_message) { fuzz_target(buffer, "blocktxn"); }
+FUZZ_TARGET_INIT(process_message_cmpctblock, initialize_process_message) { fuzz_target(buffer, "cmpctblock"); }
+FUZZ_TARGET_INIT(process_message_feefilter, initialize_process_message) { fuzz_target(buffer, "feefilter"); }
+FUZZ_TARGET_INIT(process_message_filteradd, initialize_process_message) { fuzz_target(buffer, "filteradd"); }
+FUZZ_TARGET_INIT(process_message_filterclear, initialize_process_message) { fuzz_target(buffer, "filterclear"); }
+FUZZ_TARGET_INIT(process_message_filterload, initialize_process_message) { fuzz_target(buffer, "filterload"); }
+FUZZ_TARGET_INIT(process_message_getaddr, initialize_process_message) { fuzz_target(buffer, "getaddr"); }
+FUZZ_TARGET_INIT(process_message_getblocks, initialize_process_message) { fuzz_target(buffer, "getblocks"); }
+FUZZ_TARGET_INIT(process_message_getblocktxn, initialize_process_message) { fuzz_target(buffer, "getblocktxn"); }
+FUZZ_TARGET_INIT(process_message_getdata, initialize_process_message) { fuzz_target(buffer, "getdata"); }
+FUZZ_TARGET_INIT(process_message_getheaders, initialize_process_message) { fuzz_target(buffer, "getheaders"); }
+FUZZ_TARGET_INIT(process_message_headers, initialize_process_message) { fuzz_target(buffer, "headers"); }
+FUZZ_TARGET_INIT(process_message_inv, initialize_process_message) { fuzz_target(buffer, "inv"); }
+FUZZ_TARGET_INIT(process_message_mempool, initialize_process_message) { fuzz_target(buffer, "mempool"); }
+FUZZ_TARGET_INIT(process_message_notfound, initialize_process_message) { fuzz_target(buffer, "notfound"); }
+FUZZ_TARGET_INIT(process_message_ping, initialize_process_message) { fuzz_target(buffer, "ping"); }
+FUZZ_TARGET_INIT(process_message_pong, initialize_process_message) { fuzz_target(buffer, "pong"); }
+FUZZ_TARGET_INIT(process_message_sendcmpct, initialize_process_message) { fuzz_target(buffer, "sendcmpct"); }
+FUZZ_TARGET_INIT(process_message_sendheaders, initialize_process_message) { fuzz_target(buffer, "sendheaders"); }
+FUZZ_TARGET_INIT(process_message_tx, initialize_process_message) { fuzz_target(buffer, "tx"); }
+FUZZ_TARGET_INIT(process_message_verack, initialize_process_message) { fuzz_target(buffer, "verack"); }
+FUZZ_TARGET_INIT(process_message_version, initialize_process_message) { fuzz_target(buffer, "version"); }
diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp
index f722eeac3a..e12e780a18 100644
--- a/src/test/fuzz/process_messages.cpp
+++ b/src/test/fuzz/process_messages.cpp
@@ -12,13 +12,14 @@
#include <test/util/mining.h>
#include <test/util/net.h>
#include <test/util/setup_common.h>
+#include <test/util/validation.h>
#include <util/memory.h>
#include <validation.h>
#include <validationinterface.h>
const TestingSetup* g_setup;
-void initialize()
+void initialize_process_messages()
{
static TestingSetup setup{
CBaseChainParams::REGTEST,
@@ -34,12 +35,15 @@ void initialize()
SyncWithValidationInterfaceQueue();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(process_messages, initialize_process_messages)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get();
+ TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate();
+ chainstate.ResetIbd();
std::vector<CNode*> peers;
+ bool jump_out_of_ibd{false};
const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3);
for (int i = 0; i < num_peers_to_add; ++i) {
@@ -58,6 +62,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
}
while (fuzzed_data_provider.ConsumeBool()) {
+ if (!jump_out_of_ibd) jump_out_of_ibd = fuzzed_data_provider.ConsumeBool();
+ if (jump_out_of_ibd && chainstate.IsInitialBlockDownload()) chainstate.JumpOutOfIbd();
const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()};
CSerializedNetMsg net_msg;
diff --git a/src/test/fuzz/protocol.cpp b/src/test/fuzz/protocol.cpp
index 78df0f89e7..572181366b 100644
--- a/src/test/fuzz/protocol.cpp
+++ b/src/test/fuzz/protocol.cpp
@@ -12,7 +12,7 @@
#include <stdexcept>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(protocol)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CInv> inv = ConsumeDeserializable<CInv>(fuzzed_data_provider);
diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp
index 908e2b16f2..0b4588c4ce 100644
--- a/src/test/fuzz/psbt.cpp
+++ b/src/test/fuzz/psbt.cpp
@@ -17,12 +17,12 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_psbt()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(psbt, initialize_psbt)
{
PartiallySignedTransaction psbt_mut;
const std::string raw_psbt{buffer.begin(), buffer.end()};
diff --git a/src/test/fuzz/random.cpp b/src/test/fuzz/random.cpp
index 7df6594ad6..96668734fd 100644
--- a/src/test/fuzz/random.cpp
+++ b/src/test/fuzz/random.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(random)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)};
diff --git a/src/test/fuzz/rbf.cpp b/src/test/fuzz/rbf.cpp
index 1fd88a5f7b..26c89a70c3 100644
--- a/src/test/fuzz/rbf.cpp
+++ b/src/test/fuzz/rbf.cpp
@@ -15,9 +15,10 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(rbf)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
+ SetMockTime(ConsumeTime(fuzzed_data_provider));
std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
if (!mtx) {
return;
diff --git a/src/test/fuzz/rolling_bloom_filter.cpp b/src/test/fuzz/rolling_bloom_filter.cpp
index 623b8cff3a..6087ee964a 100644
--- a/src/test/fuzz/rolling_bloom_filter.cpp
+++ b/src/test/fuzz/rolling_bloom_filter.cpp
@@ -14,7 +14,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(rolling_bloom_filter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp
index 4274fa4351..892af655f6 100644
--- a/src/test/fuzz/script.cpp
+++ b/src/test/fuzz/script.cpp
@@ -29,7 +29,7 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_script()
{
// Fuzzers using pubkey must hold an ECCVerifyHandle.
static const ECCVerifyHandle verify_handle;
@@ -37,7 +37,7 @@ void initialize()
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script, initialize_script)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CScript> script_opt = ConsumeDeserializable<CScript>(fuzzed_data_provider);
diff --git a/src/test/fuzz/script_assets_test_minimizer.cpp b/src/test/fuzz/script_assets_test_minimizer.cpp
index d20fa43d68..2091ad5d91 100644
--- a/src/test/fuzz/script_assets_test_minimizer.cpp
+++ b/src/test/fuzz/script_assets_test_minimizer.cpp
@@ -188,9 +188,9 @@ void Test(const std::string& str)
ECCVerifyHandle handle;
-}
+} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_assets_test_minimizer)
{
if (buffer.size() < 2 || buffer.back() != '\n' || buffer[buffer.size() - 2] != ',') return;
const std::string str((const char*)buffer.data(), buffer.size() - 2);
diff --git a/src/test/fuzz/script_bitcoin_consensus.cpp b/src/test/fuzz/script_bitcoin_consensus.cpp
index 22f4b4f44a..fcd66b234e 100644
--- a/src/test/fuzz/script_bitcoin_consensus.cpp
+++ b/src/test/fuzz/script_bitcoin_consensus.cpp
@@ -12,7 +12,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_bitcoin_consensus)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::vector<uint8_t> random_bytes_1 = ConsumeRandomLengthByteVector(fuzzed_data_provider);
diff --git a/src/test/fuzz/script_descriptor_cache.cpp b/src/test/fuzz/script_descriptor_cache.cpp
index 4bfe61cec7..1c62c018e7 100644
--- a/src/test/fuzz/script_descriptor_cache.cpp
+++ b/src/test/fuzz/script_descriptor_cache.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_descriptor_cache)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
DescriptorCache descriptor_cache;
diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp
index ffc65eedc0..ce8915ca2c 100644
--- a/src/test/fuzz/script_flags.cpp
+++ b/src/test/fuzz/script_flags.cpp
@@ -13,12 +13,12 @@
/** Flags that are not forbidden by an assert */
static bool IsValidFlagCombination(unsigned flags);
-void initialize()
+void initialize_script_flags()
{
static const ECCVerifyHandle verify_handle;
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script_flags, initialize_script_flags)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
@@ -31,7 +31,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
try {
const CTransaction tx(deserialize, ds);
- const PrecomputedTransactionData txdata(tx);
unsigned int verify_flags;
ds >> verify_flags;
@@ -41,10 +40,17 @@ void test_one_input(const std::vector<uint8_t>& buffer)
unsigned int fuzzed_flags;
ds >> fuzzed_flags;
+ std::vector<CTxOut> spent_outputs;
for (unsigned i = 0; i < tx.vin.size(); ++i) {
CTxOut prevout;
ds >> prevout;
+ spent_outputs.push_back(prevout);
+ }
+ PrecomputedTransactionData txdata;
+ txdata.Init(tx, std::move(spent_outputs));
+ for (unsigned i = 0; i < tx.vin.size(); ++i) {
+ const CTxOut& prevout = txdata.m_spent_outputs.at(i);
const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata};
ScriptError serror;
diff --git a/src/test/fuzz/script_interpreter.cpp b/src/test/fuzz/script_interpreter.cpp
index 26d5732f24..5d59771682 100644
--- a/src/test/fuzz/script_interpreter.cpp
+++ b/src/test/fuzz/script_interpreter.cpp
@@ -15,7 +15,7 @@
bool CastToBool(const std::vector<unsigned char>& vch);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_interpreter)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
{
diff --git a/src/test/fuzz/script_ops.cpp b/src/test/fuzz/script_ops.cpp
index 7d24af20ac..d232e984bc 100644
--- a/src/test/fuzz/script_ops.cpp
+++ b/src/test/fuzz/script_ops.cpp
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(script_ops)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
CScript script = ConsumeScript(fuzzed_data_provider);
diff --git a/src/test/fuzz/script_sigcache.cpp b/src/test/fuzz/script_sigcache.cpp
index 87af71897b..f7e45d6889 100644
--- a/src/test/fuzz/script_sigcache.cpp
+++ b/src/test/fuzz/script_sigcache.cpp
@@ -16,7 +16,7 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_script_sigcache()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
@@ -24,12 +24,12 @@ void initialize()
InitSignatureCache();
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script_sigcache, initialize_script_sigcache)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::optional<CMutableTransaction> mutable_transaction = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
- const CTransaction tx = mutable_transaction ? CTransaction{*mutable_transaction} : CTransaction{};
+ const CTransaction tx{mutable_transaction ? *mutable_transaction : CMutableTransaction{}};
const unsigned int n_in = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
const CAmount amount = ConsumeMoney(fuzzed_data_provider);
const bool store = fuzzed_data_provider.ConsumeBool();
diff --git a/src/test/fuzz/script_sign.cpp b/src/test/fuzz/script_sign.cpp
index c626f950e7..fe850a6959 100644
--- a/src/test/fuzz/script_sign.cpp
+++ b/src/test/fuzz/script_sign.cpp
@@ -22,14 +22,14 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_script_sign()
{
static const ECCVerifyHandle ecc_verify_handle;
ECC_Start();
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(script_sign, initialize_script_sign)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::vector<uint8_t> key = ConsumeRandomLengthByteVector(fuzzed_data_provider, 128);
diff --git a/src/test/fuzz/scriptnum_ops.cpp b/src/test/fuzz/scriptnum_ops.cpp
index 68c1ae58ca..650318f13c 100644
--- a/src/test/fuzz/scriptnum_ops.cpp
+++ b/src/test/fuzz/scriptnum_ops.cpp
@@ -24,7 +24,7 @@ bool IsValidSubtraction(const CScriptNum& lhs, const CScriptNum& rhs)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(scriptnum_ops)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
CScriptNum script_num = ConsumeScriptNum(fuzzed_data_provider);
diff --git a/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp b/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
index d4f302a8d3..0435626356 100644
--- a/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
+++ b/src/test/fuzz/secp256k1_ec_seckey_import_export_der.cpp
@@ -14,7 +14,7 @@
int ec_seckey_import_der(const secp256k1_context* ctx, unsigned char* out32, const unsigned char* seckey, size_t seckeylen);
int ec_seckey_export_der(const secp256k1_context* ctx, unsigned char* seckey, size_t* seckeylen, const unsigned char* key32, bool compressed);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(secp256k1_ec_seckey_import_export_der)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
secp256k1_context* secp256k1_context_sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
diff --git a/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp b/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
index ed8c7aba89..f437d53b57 100644
--- a/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
+++ b/src/test/fuzz/secp256k1_ecdsa_signature_parse_der_lax.cpp
@@ -14,7 +14,7 @@
bool SigHasLowR(const secp256k1_ecdsa_signature* sig);
int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char* input, size_t inputlen);
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(secp256k1_ecdsa_signature_parse_der_lax)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::vector<uint8_t> signature_bytes = ConsumeRandomLengthByteVector(fuzzed_data_provider);
diff --git a/src/test/fuzz/signature_checker.cpp b/src/test/fuzz/signature_checker.cpp
index e121c89665..3e7b72805e 100644
--- a/src/test/fuzz/signature_checker.cpp
+++ b/src/test/fuzz/signature_checker.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void initialize()
+void initialize_signature_checker()
{
static const auto verify_handle = MakeUnique<ECCVerifyHandle>();
}
@@ -24,7 +24,7 @@ class FuzzedSignatureChecker : public BaseSignatureChecker
FuzzedDataProvider& m_fuzzed_data_provider;
public:
- FuzzedSignatureChecker(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider(fuzzed_data_provider)
+ explicit FuzzedSignatureChecker(FuzzedDataProvider& fuzzed_data_provider) : m_fuzzed_data_provider(fuzzed_data_provider)
{
}
@@ -52,7 +52,7 @@ public:
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(signature_checker, initialize_signature_checker)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
diff --git a/src/test/fuzz/signet.cpp b/src/test/fuzz/signet.cpp
index 786f1a83fe..541322d484 100644
--- a/src/test/fuzz/signet.cpp
+++ b/src/test/fuzz/signet.cpp
@@ -15,12 +15,12 @@
#include <optional>
#include <vector>
-void initialize()
+void initialize_signet()
{
InitializeFuzzingContext(CBaseChainParams::SIGNET);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(signet, initialize_signet)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const std::optional<CBlock> block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
diff --git a/src/test/fuzz/span.cpp b/src/test/fuzz/span.cpp
index f6b6e8f6f0..8f753948df 100644
--- a/src/test/fuzz/span.cpp
+++ b/src/test/fuzz/span.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(span)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
diff --git a/src/test/fuzz/spanparsing.cpp b/src/test/fuzz/spanparsing.cpp
index e5bf5dd608..293a7e7e90 100644
--- a/src/test/fuzz/spanparsing.cpp
+++ b/src/test/fuzz/spanparsing.cpp
@@ -6,7 +6,7 @@
#include <test/fuzz/fuzz.h>
#include <util/spanparsing.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(spanparsing)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const size_t query_size = fuzzed_data_provider.ConsumeIntegral<size_t>();
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index 271062dc95..282a2cd8ca 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -33,7 +33,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(string)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string random_string_1 = fuzzed_data_provider.ConsumeRandomLengthString(32);
diff --git a/src/test/fuzz/strprintf.cpp b/src/test/fuzz/strprintf.cpp
index 29064bc45c..4af0e750ce 100644
--- a/src/test/fuzz/strprintf.cpp
+++ b/src/test/fuzz/strprintf.cpp
@@ -13,7 +13,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(str_printf)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const std::string format_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
diff --git a/src/test/fuzz/system.cpp b/src/test/fuzz/system.cpp
index 01b523cee4..375a8c1ed0 100644
--- a/src/test/fuzz/system.cpp
+++ b/src/test/fuzz/system.cpp
@@ -22,7 +22,7 @@ std::string GetArgumentName(const std::string& name)
}
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(system)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
ArgsManager args_manager{};
diff --git a/src/test/fuzz/timedata.cpp b/src/test/fuzz/timedata.cpp
index a0e579a88f..d7fa66298a 100644
--- a/src/test/fuzz/timedata.cpp
+++ b/src/test/fuzz/timedata.cpp
@@ -11,7 +11,7 @@
#include <string>
#include <vector>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(timedata)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const unsigned int max_size = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, 1000);
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index d6deb7fc3d..13ae450756 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -21,12 +21,12 @@
#include <cassert>
-void initialize()
+void initialize_transaction()
{
SelectParams(CBaseChainParams::REGTEST);
}
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET_INIT(transaction, initialize_transaction)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
try {
@@ -42,7 +42,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
return CTransaction(deserialize, ds);
} catch (const std::ios_base::failure&) {
valid_tx = false;
- return CTransaction();
+ return CTransaction{CMutableTransaction{}};
}
}();
bool valid_mutable_tx = true;
@@ -95,7 +95,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
CCoinsView coins_view;
const CCoinsViewCache coins_view_cache(&coins_view);
- (void)AreInputsStandard(tx, coins_view_cache);
+ (void)AreInputsStandard(tx, coins_view_cache, false);
+ (void)AreInputsStandard(tx, coins_view_cache, true);
(void)IsWitnessStandard(tx, coins_view_cache);
UniValue u(UniValue::VOBJ);
diff --git a/src/test/fuzz/tx_in.cpp b/src/test/fuzz/tx_in.cpp
index 8e116537d1..dd94922b86 100644
--- a/src/test/fuzz/tx_in.cpp
+++ b/src/test/fuzz/tx_in.cpp
@@ -12,7 +12,7 @@
#include <cassert>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(tx_in)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
CTxIn tx_in;
diff --git a/src/test/fuzz/tx_out.cpp b/src/test/fuzz/tx_out.cpp
index aa1338d5ba..5e22c4adc5 100644
--- a/src/test/fuzz/tx_out.cpp
+++ b/src/test/fuzz/tx_out.cpp
@@ -10,7 +10,7 @@
#include <test/fuzz/fuzz.h>
#include <version.h>
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(tx_out)
{
CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
CTxOut tx_out;
diff --git a/src/test/fuzz/txrequest.cpp b/src/test/fuzz/txrequest.cpp
index 9529ad3274..72438ff2d7 100644
--- a/src/test/fuzz/txrequest.cpp
+++ b/src/test/fuzz/txrequest.cpp
@@ -310,7 +310,7 @@ public:
};
} // namespace
-void test_one_input(const std::vector<uint8_t>& buffer)
+FUZZ_TARGET(txrequest)
{
// Tester object (which encapsulates a TxRequestTracker).
Tester tester;
diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h
index ed6093a8a8..cf666a8b93 100644
--- a/src/test/fuzz/util.h
+++ b/src/test/fuzz/util.h
@@ -11,6 +11,8 @@
#include <chainparamsbase.h>
#include <coins.h>
#include <consensus/consensus.h>
+#include <merkleblock.h>
+#include <net.h>
#include <netaddress.h>
#include <netbase.h>
#include <primitives/transaction.h>
@@ -23,6 +25,7 @@
#include <test/util/setup_common.h>
#include <txmempool.h>
#include <uint256.h>
+#include <util/time.h>
#include <version.h>
#include <algorithm>
@@ -32,18 +35,23 @@
#include <string>
#include <vector>
-NODISCARD inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
+[[nodiscard]] inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
{
const std::string s = fuzzed_data_provider.ConsumeRandomLengthString(max_length);
return {s.begin(), s.end()};
}
-NODISCARD inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
+[[nodiscard]] inline std::vector<bool> ConsumeRandomLengthBitVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
+{
+ return BytesToBits(ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length));
+}
+
+[[nodiscard]] inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
{
return {ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length), SER_NETWORK, INIT_PROTO_VERSION};
}
-NODISCARD inline std::vector<std::string> ConsumeRandomLengthStringVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16, const size_t max_string_length = 16) noexcept
+[[nodiscard]] inline std::vector<std::string> ConsumeRandomLengthStringVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16, const size_t max_string_length = 16) noexcept
{
const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
std::vector<std::string> r;
@@ -54,7 +62,7 @@ NODISCARD inline std::vector<std::string> ConsumeRandomLengthStringVector(Fuzzed
}
template <typename T>
-NODISCARD inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16) noexcept
+[[nodiscard]] inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16) noexcept
{
const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);
std::vector<T> r;
@@ -65,7 +73,7 @@ NODISCARD inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProv
}
template <typename T>
-NODISCARD inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
+[[nodiscard]] inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
{
const std::vector<uint8_t> buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length);
CDataStream ds{buffer, SER_NETWORK, INIT_PROTO_VERSION};
@@ -78,28 +86,36 @@ NODISCARD inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzz
return obj;
}
-NODISCARD inline opcodetype ConsumeOpcodeType(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline opcodetype ConsumeOpcodeType(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return static_cast<opcodetype>(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE));
}
-NODISCARD inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, MAX_MONEY);
}
-NODISCARD inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ // Avoid t=0 (1970-01-01T00:00:00Z) since SetMockTime(0) is a no-op.
+ static const int64_t time_min = ParseISO8601DateTime("1970-01-01T00:00:01Z");
+ static const int64_t time_max = ParseISO8601DateTime("9999-12-31T23:59:59Z");
+ return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(time_min, time_max);
+}
+
+[[nodiscard]] inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider);
return {b.begin(), b.end()};
}
-NODISCARD inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};
}
-NODISCARD inline uint160 ConsumeUInt160(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline uint160 ConsumeUInt160(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
const std::vector<uint8_t> v160 = fuzzed_data_provider.ConsumeBytes<uint8_t>(160 / 8);
if (v160.size() != 160 / 8) {
@@ -108,7 +124,7 @@ NODISCARD inline uint160 ConsumeUInt160(FuzzedDataProvider& fuzzed_data_provider
return uint160{v160};
}
-NODISCARD inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
const std::vector<uint8_t> v256 = fuzzed_data_provider.ConsumeBytes<uint8_t>(256 / 8);
if (v256.size() != 256 / 8) {
@@ -117,12 +133,12 @@ NODISCARD inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider
return uint256{v256};
}
-NODISCARD inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return UintToArith256(ConsumeUInt256(fuzzed_data_provider));
}
-NODISCARD inline CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzzed_data_provider, const CTransaction& tx) noexcept
+[[nodiscard]] inline CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzzed_data_provider, const CTransaction& tx) noexcept
{
// Avoid:
// policy/feerate.cpp:28:34: runtime error: signed integer overflow: 34873208148477500 * 1000 cannot be represented in type 'long'
@@ -137,7 +153,7 @@ NODISCARD inline CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzze
return CTxMemPoolEntry{MakeTransactionRef(tx), fee, time, entry_height, spends_coinbase, sig_op_cost, {}};
}
-NODISCARD inline CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
CTxDestination tx_destination;
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 5)) {
@@ -175,7 +191,7 @@ NODISCARD inline CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_
}
template <typename T>
-NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept
+[[nodiscard]] bool MultiplicationOverflow(const T i, const T j) noexcept
{
static_assert(std::is_integral<T>::value, "Integral required.");
if (std::numeric_limits<T>::is_signed) {
@@ -198,7 +214,7 @@ NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept
}
template <class T>
-NODISCARD bool AdditionOverflow(const T i, const T j) noexcept
+[[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept
{
static_assert(std::is_integral<T>::value, "Integral required.");
if (std::numeric_limits<T>::is_signed) {
@@ -208,7 +224,7 @@ NODISCARD bool AdditionOverflow(const T i, const T j) noexcept
return std::numeric_limits<T>::max() - i < j;
}
-NODISCARD inline bool ContainsSpentInput(const CTransaction& tx, const CCoinsViewCache& inputs) noexcept
+[[nodiscard]] inline bool ContainsSpentInput(const CTransaction& tx, const CCoinsViewCache& inputs) noexcept
{
for (const CTxIn& tx_in : tx.vin) {
const Coin& coin = inputs.AccessCoin(tx_in.prevout);
@@ -223,7 +239,7 @@ NODISCARD inline bool ContainsSpentInput(const CTransaction& tx, const CCoinsVie
* Returns a byte vector of specified size regardless of the number of remaining bytes available
* from the fuzzer. Pads with zero value bytes if needed to achieve the specified size.
*/
-NODISCARD inline std::vector<uint8_t> ConsumeFixedLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t length) noexcept
+[[nodiscard]] inline std::vector<uint8_t> ConsumeFixedLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const size_t length) noexcept
{
std::vector<uint8_t> result(length);
const std::vector<uint8_t> random_bytes = fuzzed_data_provider.ConsumeBytes<uint8_t>(length);
@@ -260,6 +276,32 @@ CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept
return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint8_t>()};
}
+CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()};
+}
+
+CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ return {ConsumeService(fuzzed_data_provider), static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()), fuzzed_data_provider.ConsumeIntegral<uint32_t>()};
+}
+
+CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept
+{
+ const NodeId node_id = fuzzed_data_provider.ConsumeIntegral<NodeId>();
+ const ServiceFlags local_services = static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ const int my_starting_height = fuzzed_data_provider.ConsumeIntegral<int>();
+ const SOCKET socket = INVALID_SOCKET;
+ const CAddress address = ConsumeAddress(fuzzed_data_provider);
+ const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
+ const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
+ const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider);
+ const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64);
+ const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH});
+ const bool inbound_onion = fuzzed_data_provider.ConsumeBool();
+ return {node_id, local_services, my_starting_height, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion};
+}
+
void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST)
{
static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}};
@@ -378,7 +420,7 @@ public:
}
};
-NODISCARD inline FuzzedFileProvider ConsumeFile(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline FuzzedFileProvider ConsumeFile(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return {fuzzed_data_provider};
}
@@ -399,7 +441,7 @@ public:
}
};
-NODISCARD inline FuzzedAutoFileProvider ConsumeAutoFile(FuzzedDataProvider& fuzzed_data_provider) noexcept
+[[nodiscard]] inline FuzzedAutoFileProvider ConsumeAutoFile(FuzzedDataProvider& fuzzed_data_provider) noexcept
{
return {fuzzed_data_provider};
}
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
index b0d4de89f3..73463b071e 100644
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -17,8 +17,8 @@ BOOST_FIXTURE_TEST_SUITE(interfaces_tests, TestChain100Setup)
BOOST_AUTO_TEST_CASE(findBlock)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
BOOST_CHECK(chain->findBlock(active[10]->GetBlockHash(), FoundBlock().hash(hash)));
@@ -44,13 +44,25 @@ BOOST_AUTO_TEST_CASE(findBlock)
BOOST_CHECK(chain->findBlock(active[60]->GetBlockHash(), FoundBlock().mtpTime(mtp_time)));
BOOST_CHECK_EQUAL(mtp_time, active[60]->GetMedianTimePast());
+ bool cur_active{false}, next_active{false};
+ uint256 next_hash;
+ BOOST_CHECK_EQUAL(active.Height(), 100);
+ BOOST_CHECK(chain->findBlock(active[99]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active).hash(next_hash))));
+ BOOST_CHECK(cur_active);
+ BOOST_CHECK(next_active);
+ BOOST_CHECK_EQUAL(next_hash, active[100]->GetBlockHash());
+ cur_active = next_active = false;
+ BOOST_CHECK(chain->findBlock(active[100]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active))));
+ BOOST_CHECK(cur_active);
+ BOOST_CHECK(!next_active);
+
BOOST_CHECK(!chain->findBlock({}, FoundBlock()));
}
BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
int height;
BOOST_CHECK(chain->findFirstBlockWithTimeAndHeight(/* min_time= */ 0, /* min_height= */ 5, FoundBlock().hash(hash).height(height)));
@@ -59,25 +71,10 @@ BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
BOOST_CHECK(!chain->findFirstBlockWithTimeAndHeight(/* min_time= */ active.Tip()->GetBlockTimeMax() + 1, /* min_height= */ 0));
}
-BOOST_AUTO_TEST_CASE(findNextBlock)
-{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
- bool reorg;
- uint256 hash;
- BOOST_CHECK(chain->findNextBlock(active[20]->GetBlockHash(), 20, FoundBlock().hash(hash), &reorg));
- BOOST_CHECK_EQUAL(hash, active[21]->GetBlockHash());
- BOOST_CHECK_EQUAL(reorg, false);
- BOOST_CHECK(!chain->findNextBlock(uint256(), 20, {}, &reorg));
- BOOST_CHECK_EQUAL(reorg, true);
- BOOST_CHECK(!chain->findNextBlock(active.Tip()->GetBlockHash(), active.Height(), {}, &reorg));
- BOOST_CHECK_EQUAL(reorg, false);
-}
-
BOOST_AUTO_TEST_CASE(findAncestorByHeight)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
BOOST_CHECK(chain->findAncestorByHeight(active[20]->GetBlockHash(), 10, FoundBlock().hash(hash)));
BOOST_CHECK_EQUAL(hash, active[10]->GetBlockHash());
@@ -86,8 +83,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHeight)
BOOST_AUTO_TEST_CASE(findAncestorByHash)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
int height = -1;
BOOST_CHECK(chain->findAncestorByHash(active[20]->GetBlockHash(), active[10]->GetBlockHash(), FoundBlock().height(height)));
BOOST_CHECK_EQUAL(height, 10);
@@ -96,8 +93,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHash)
BOOST_AUTO_TEST_CASE(findCommonAncestor)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
auto* orig_tip = active.Tip();
for (int i = 0; i < 10; ++i) {
BlockValidationState state;
@@ -126,8 +123,8 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor)
BOOST_AUTO_TEST_CASE(hasBlocks)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
// Test ranges
BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 3362b8d17c..cb66d5164e 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -172,20 +172,30 @@ BOOST_AUTO_TEST_CASE(key_signature_tests)
}
BOOST_CHECK(found);
- // When entropy is not specified, we should always see low R signatures that are less than 70 bytes in 256 tries
+ // When entropy is not specified, we should always see low R signatures that are less than or equal to 70 bytes in 256 tries
+ // The low R signatures should always have the value of their "length of R" byte less than or equal to 32
// We should see at least one signature that is less than 70 bytes.
- found = true;
bool found_small = false;
+ bool found_big = false;
+ bool bad_sign = false;
for (int i = 0; i < 256; ++i) {
sig.clear();
std::string msg = "A message to be signed" + ToString(i);
msg_hash = Hash(msg);
- BOOST_CHECK(key.Sign(msg_hash, sig));
- found = sig[3] == 0x20;
- BOOST_CHECK(sig.size() <= 70);
+ if (!key.Sign(msg_hash, sig)) {
+ bad_sign = true;
+ break;
+ }
+ // sig.size() > 70 implies sig[3] > 32, because S is always low.
+ // But check both conditions anyway, just in case this implication is broken for some reason
+ if (sig[3] > 32 || sig.size() > 70) {
+ found_big = true;
+ break;
+ }
found_small |= sig.size() < 70;
}
- BOOST_CHECK(found);
+ BOOST_CHECK(!bad_sign);
+ BOOST_CHECK(!found_big);
BOOST_CHECK(found_small);
}
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index 37eca8b7ef..beac65942e 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -9,6 +9,7 @@
#include <cstdint>
#include <net.h>
#include <netbase.h>
+#include <optional.h>
#include <serialize.h>
#include <span.h>
#include <streams.h>
@@ -21,10 +22,13 @@
#include <boost/test/unit_test.hpp>
+#include <algorithm>
#include <ios>
#include <memory>
#include <string>
+using namespace std::literals;
+
class CAddrManSerializationMock : public CAddrMan
{
public:
@@ -73,7 +77,7 @@ public:
}
};
-static CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
+static CDataStream AddrmanToStream(const CAddrManSerializationMock& _addrman)
{
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
ssPeersIn << Params().MessageStart();
@@ -106,8 +110,8 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
- BOOST_CHECK(Lookup(std::string("250.7.3.3", 9), addr3, 9999, false));
- BOOST_CHECK(!Lookup(std::string("250.7.3.3\0example.com", 21), addr3, 9999, false));
+ BOOST_CHECK(Lookup("250.7.3.3"s, addr3, 9999, false));
+ BOOST_CHECK(!Lookup("250.7.3.3\0example.com"s, addr3, 9999, false));
// Add three addresses to new table.
CService source;
@@ -602,6 +606,16 @@ BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
BOOST_CHECK_EQUAL(addr.ToString(), "fc00:1:2:3:4:5:6:7");
BOOST_REQUIRE(s.empty());
+ // Invalid CJDNS, wrong prefix.
+ s << MakeSpan(ParseHex("06" // network type (CJDNS)
+ "10" // address length
+ "aa000001000200030004000500060007" // address
+ ));
+ s >> addr;
+ BOOST_CHECK(addr.IsCJDNS());
+ BOOST_CHECK(!addr.IsValid());
+ BOOST_REQUIRE(s.empty());
+
// Invalid CJDNS, with bogus length.
s << MakeSpan(ParseHex("06" // network type (CJDNS)
"01" // address length
@@ -769,4 +783,147 @@ BOOST_AUTO_TEST_CASE(PoissonNextSend)
g_mock_deterministic_tests = false;
}
+std::vector<NodeEvictionCandidate> GetRandomNodeEvictionCandidates(const int n_candidates, FastRandomContext& random_context)
+{
+ std::vector<NodeEvictionCandidate> candidates;
+ for (int id = 0; id < n_candidates; ++id) {
+ candidates.push_back({
+ /* id */ id,
+ /* nTimeConnected */ static_cast<int64_t>(random_context.randrange(100)),
+ /* nMinPingUsecTime */ static_cast<int64_t>(random_context.randrange(100)),
+ /* nLastBlockTime */ static_cast<int64_t>(random_context.randrange(100)),
+ /* nLastTXTime */ static_cast<int64_t>(random_context.randrange(100)),
+ /* fRelevantServices */ random_context.randbool(),
+ /* fRelayTxes */ random_context.randbool(),
+ /* fBloomFilter */ random_context.randbool(),
+ /* nKeyedNetGroup */ random_context.randrange(100),
+ /* prefer_evict */ random_context.randbool(),
+ /* m_is_local */ random_context.randbool(),
+ });
+ }
+ return candidates;
+}
+
+// Returns true if any of the node ids in node_ids are selected for eviction.
+bool IsEvicted(std::vector<NodeEvictionCandidate> candidates, const std::vector<NodeId>& node_ids, FastRandomContext& random_context)
+{
+ Shuffle(candidates.begin(), candidates.end(), random_context);
+ const Optional<NodeId> evicted_node_id = SelectNodeToEvict(std::move(candidates));
+ if (!evicted_node_id) {
+ return false;
+ }
+ return std::find(node_ids.begin(), node_ids.end(), *evicted_node_id) != node_ids.end();
+}
+
+// Create number_of_nodes random nodes, apply setup function candidate_setup_fn,
+// apply eviction logic and then return true if any of the node ids in node_ids
+// are selected for eviction.
+bool IsEvicted(const int number_of_nodes, std::function<void(NodeEvictionCandidate&)> candidate_setup_fn, const std::vector<NodeId>& node_ids, FastRandomContext& random_context)
+{
+ std::vector<NodeEvictionCandidate> candidates = GetRandomNodeEvictionCandidates(number_of_nodes, random_context);
+ for (NodeEvictionCandidate& candidate : candidates) {
+ candidate_setup_fn(candidate);
+ }
+ return IsEvicted(candidates, node_ids, random_context);
+}
+
+namespace {
+constexpr int NODE_EVICTION_TEST_ROUNDS{10};
+constexpr int NODE_EVICTION_TEST_UP_TO_N_NODES{200};
+} // namespace
+
+BOOST_AUTO_TEST_CASE(node_eviction_test)
+{
+ FastRandomContext random_context{true};
+
+ for (int i = 0; i < NODE_EVICTION_TEST_ROUNDS; ++i) {
+ for (int number_of_nodes = 0; number_of_nodes < NODE_EVICTION_TEST_UP_TO_N_NODES; ++number_of_nodes) {
+ // Four nodes with the highest keyed netgroup values should be
+ // protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nKeyedNetGroup = number_of_nodes - candidate.id;
+ },
+ {0, 1, 2, 3}, random_context));
+
+ // Eight nodes with the lowest minimum ping time should be protected
+ // from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [](NodeEvictionCandidate& candidate) {
+ candidate.nMinPingUsecTime = candidate.id;
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7}, random_context));
+
+ // Four nodes that most recently sent us novel transactions accepted
+ // into our mempool should be protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastTXTime = number_of_nodes - candidate.id;
+ },
+ {0, 1, 2, 3}, random_context));
+
+ // Up to eight non-tx-relay peers that most recently sent us novel
+ // blocks should be protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastBlockTime = number_of_nodes - candidate.id;
+ if (candidate.id <= 7) {
+ candidate.fRelayTxes = false;
+ candidate.fRelevantServices = true;
+ }
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7}, random_context));
+
+ // Four peers that most recently sent us novel blocks should be
+ // protected from eviction.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastBlockTime = number_of_nodes - candidate.id;
+ },
+ {0, 1, 2, 3}, random_context));
+
+ // Combination of the previous two tests.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nLastBlockTime = number_of_nodes - candidate.id;
+ if (candidate.id <= 7) {
+ candidate.fRelayTxes = false;
+ candidate.fRelevantServices = true;
+ }
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, random_context));
+
+ // Combination of all tests above.
+ BOOST_CHECK(!IsEvicted(
+ number_of_nodes, [number_of_nodes](NodeEvictionCandidate& candidate) {
+ candidate.nKeyedNetGroup = number_of_nodes - candidate.id; // 4 protected
+ candidate.nMinPingUsecTime = candidate.id; // 8 protected
+ candidate.nLastTXTime = number_of_nodes - candidate.id; // 4 protected
+ candidate.nLastBlockTime = number_of_nodes - candidate.id; // 4 protected
+ },
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}, random_context));
+
+ // An eviction is expected given >= 29 random eviction candidates. The eviction logic protects at most
+ // four peers by net group, eight by lowest ping time, four by last time of novel tx, up to eight non-tx-relay
+ // peers by last novel block time, and four more peers by last novel block time.
+ if (number_of_nodes >= 29) {
+ BOOST_CHECK(SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context)));
+ }
+
+ // No eviction is expected given <= 20 random eviction candidates. The eviction logic protects at least
+ // four peers by net group, eight by lowest ping time, four by last time of novel tx and four peers by last
+ // novel block time.
+ if (number_of_nodes <= 20) {
+ BOOST_CHECK(!SelectNodeToEvict(GetRandomNodeEvictionCandidates(number_of_nodes, random_context)));
+ }
+
+ // Cases left to test:
+ // * "Protect the half of the remaining nodes which have been connected the longest. [...]"
+ // * "Pick out up to 1/4 peers that are localhost, sorted by longest uptime. [...]"
+ // * "If any remaining peers are preferred for eviction consider only them. [...]"
+ // * "Identify the network group with the most connections and youngest member. [...]"
+ }
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index f5d26fafef..ac4db3a5b6 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -16,6 +16,8 @@
#include <boost/test/unit_test.hpp>
+using namespace std::literals;
+
BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup)
static CNetAddr ResolveIP(const std::string& ip)
@@ -431,20 +433,20 @@ BOOST_AUTO_TEST_CASE(netpermissions_test)
BOOST_AUTO_TEST_CASE(netbase_dont_resolve_strings_with_embedded_nul_characters)
{
CNetAddr addr;
- BOOST_CHECK(LookupHost(std::string("127.0.0.1", 9), addr, false));
- BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0", 10), addr, false));
- BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com", 21), addr, false));
- BOOST_CHECK(!LookupHost(std::string("127.0.0.1\0example.com\0", 22), addr, false));
+ BOOST_CHECK(LookupHost("127.0.0.1"s, addr, false));
+ BOOST_CHECK(!LookupHost("127.0.0.1\0"s, addr, false));
+ BOOST_CHECK(!LookupHost("127.0.0.1\0example.com"s, addr, false));
+ BOOST_CHECK(!LookupHost("127.0.0.1\0example.com\0"s, addr, false));
CSubNet ret;
- BOOST_CHECK(LookupSubNet(std::string("1.2.3.0/24", 10), ret));
- BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0", 11), ret));
- BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com", 22), ret));
- BOOST_CHECK(!LookupSubNet(std::string("1.2.3.0/24\0example.com\0", 23), ret));
+ BOOST_CHECK(LookupSubNet("1.2.3.0/24"s, ret));
+ BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0"s, ret));
+ BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com"s, ret));
+ BOOST_CHECK(!LookupSubNet("1.2.3.0/24\0example.com\0"s, ret));
// We only do subnetting for IPv4 and IPv6
- BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion", 22), ret));
- BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0", 23), ret));
- BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com", 34), ret));
- BOOST_CHECK(!LookupSubNet(std::string("5wyqrzbvrdsumnok.onion\0example.com\0", 35), ret));
+ BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion"s, ret));
+ BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0"s, ret));
+ BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com"s, ret));
+ BOOST_CHECK(!LookupSubNet("5wyqrzbvrdsumnok.onion\0example.com\0"s, ret));
}
// Since CNetAddr (un)ser is tested separately in net_tests.cpp here we only
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
index a42608a66d..7da364d316 100644
--- a/src/test/reverselock_tests.cpp
+++ b/src/test/reverselock_tests.cpp
@@ -48,12 +48,14 @@ BOOST_AUTO_TEST_CASE(reverselock_errors)
WAIT_LOCK(mutex, lock);
#ifdef DEBUG_LOCKORDER
+ bool prev = g_debug_lockorder_abort;
+ g_debug_lockorder_abort = false;
+
// Make sure trying to reverse lock a previous lock fails
- try {
- REVERSE_LOCK(lock2);
- BOOST_CHECK(false); // REVERSE_LOCK(lock2) succeeded
- } catch(...) { }
+ BOOST_CHECK_EXCEPTION(REVERSE_LOCK(lock2), std::logic_error, HasReason("lock2 was not most recent critical section locked"));
BOOST_CHECK(lock2.owns_lock());
+
+ g_debug_lockorder_abort = prev;
#endif
// Make sure trying to reverse lock an unlocked lock fails
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index f6824a4e5e..856ec6346d 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txTo.vin[3].scriptSig << OP_11 << OP_11 << std::vector<unsigned char>(oneAndTwo.begin(), oneAndTwo.end());
txTo.vin[4].scriptSig << std::vector<unsigned char>(fifteenSigops.begin(), fifteenSigops.end());
- BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins));
+ BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins, false));
// 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U);
@@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txToNonStd1.vin[0].prevout.hash = txFrom.GetHash();
txToNonStd1.vin[0].scriptSig << std::vector<unsigned char>(sixteenSigops.begin(), sixteenSigops.end());
- BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins));
+ BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins, false));
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U);
CMutableTransaction txToNonStd2;
@@ -368,7 +368,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txToNonStd2.vin[0].prevout.hash = txFrom.GetHash();
txToNonStd2.vin[0].scriptSig << std::vector<unsigned char>(twentySigops.begin(), twentySigops.end());
- BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins));
+ BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins, false));
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U);
}
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index a2efd8ac07..25ca171b33 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -106,18 +106,18 @@ static ScriptErrorDesc script_errors[]={
static std::string FormatScriptError(ScriptError_t err)
{
- for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
- if (script_errors[i].err == err)
- return script_errors[i].name;
+ for (const auto& se : script_errors)
+ if (se.err == err)
+ return se.name;
BOOST_ERROR("Unknown scripterror enumeration value, update script_errors in script_tests.cpp.");
return "";
}
-static ScriptError_t ParseScriptError(const std::string &name)
+static ScriptError_t ParseScriptError(const std::string& name)
{
- for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
- if (script_errors[i].name == name)
- return script_errors[i].err;
+ for (const auto& se : script_errors)
+ if (se.name == name)
+ return se.err;
BOOST_ERROR("Unknown scripterror \"" << name << "\" in test description");
return SCRIPT_ERR_UNKNOWN_ERROR;
}
@@ -1347,36 +1347,6 @@ static CScript ScriptFromHex(const std::string& str)
return CScript(data.begin(), data.end());
}
-static CMutableTransaction TxFromHex(const std::string& str)
-{
- CMutableTransaction tx;
- VectorReader(SER_DISK, SERIALIZE_TRANSACTION_NO_WITNESS, ParseHex(str), 0) >> tx;
- return tx;
-}
-
-static std::vector<CTxOut> TxOutsFromJSON(const UniValue& univalue)
-{
- assert(univalue.isArray());
- std::vector<CTxOut> prevouts;
- for (size_t i = 0; i < univalue.size(); ++i) {
- CTxOut txout;
- VectorReader(SER_DISK, 0, ParseHex(univalue[i].get_str()), 0) >> txout;
- prevouts.push_back(std::move(txout));
- }
- return prevouts;
-}
-
-static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
-{
- assert(univalue.isArray());
- CScriptWitness scriptwitness;
- for (size_t i = 0; i < univalue.size(); ++i) {
- auto bytes = ParseHex(univalue[i].get_str());
- scriptwitness.stack.push_back(std::move(bytes));
- }
- return scriptwitness;
-}
-
BOOST_AUTO_TEST_CASE(script_FindAndDelete)
{
// Exercise the FindAndDelete functionality
@@ -1500,6 +1470,36 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps)
BOOST_CHECK(!script.HasValidOps());
}
+static CMutableTransaction TxFromHex(const std::string& str)
+{
+ CMutableTransaction tx;
+ VectorReader(SER_DISK, SERIALIZE_TRANSACTION_NO_WITNESS, ParseHex(str), 0) >> tx;
+ return tx;
+}
+
+static std::vector<CTxOut> TxOutsFromJSON(const UniValue& univalue)
+{
+ assert(univalue.isArray());
+ std::vector<CTxOut> prevouts;
+ for (size_t i = 0; i < univalue.size(); ++i) {
+ CTxOut txout;
+ VectorReader(SER_DISK, 0, ParseHex(univalue[i].get_str()), 0) >> txout;
+ prevouts.push_back(std::move(txout));
+ }
+ return prevouts;
+}
+
+static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue)
+{
+ assert(univalue.isArray());
+ CScriptWitness scriptwitness;
+ for (size_t i = 0; i < univalue.size(); ++i) {
+ auto bytes = ParseHex(univalue[i].get_str());
+ scriptwitness.stack.push_back(std::move(bytes));
+ }
+ return scriptwitness;
+}
+
#if defined(HAVE_CONSENSUS_LIB)
/* Test simple (successful) usage of bitcoinconsensus_verify_script */
@@ -1640,6 +1640,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags)
BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_INVALID_FLAGS);
}
+#endif // defined(HAVE_CONSENSUS_LIB)
+
static std::vector<unsigned int> AllConsensusFlags()
{
std::vector<unsigned int> ret;
@@ -1742,5 +1744,4 @@ BOOST_AUTO_TEST_CASE(script_assets_test)
file.close();
}
-#endif
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sync_tests.cpp b/src/test/sync_tests.cpp
index 19029ebd3c..71275f69d9 100644
--- a/src/test/sync_tests.cpp
+++ b/src/test/sync_tests.cpp
@@ -6,6 +6,9 @@
#include <test/util/setup_common.h>
#include <boost/test/unit_test.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include <mutex>
namespace {
template <typename MutexType>
@@ -29,6 +32,49 @@ void TestPotentialDeadLockDetected(MutexType& mutex1, MutexType& mutex2)
BOOST_CHECK(!error_thrown);
#endif
}
+
+#ifdef DEBUG_LOCKORDER
+template <typename MutexType>
+void TestDoubleLock2(MutexType& m)
+{
+ ENTER_CRITICAL_SECTION(m);
+ LEAVE_CRITICAL_SECTION(m);
+}
+
+template <typename MutexType>
+void TestDoubleLock(bool should_throw)
+{
+ const bool prev = g_debug_lockorder_abort;
+ g_debug_lockorder_abort = false;
+
+ MutexType m;
+ ENTER_CRITICAL_SECTION(m);
+ if (should_throw) {
+ BOOST_CHECK_EXCEPTION(TestDoubleLock2(m), std::logic_error,
+ HasReason("double lock detected"));
+ } else {
+ BOOST_CHECK_NO_THROW(TestDoubleLock2(m));
+ }
+ LEAVE_CRITICAL_SECTION(m);
+
+ BOOST_CHECK(LockStackEmpty());
+
+ g_debug_lockorder_abort = prev;
+}
+#endif /* DEBUG_LOCKORDER */
+
+template <typename MutexType>
+void TestInconsistentLockOrderDetected(MutexType& mutex1, MutexType& mutex2) NO_THREAD_SAFETY_ANALYSIS
+{
+ ENTER_CRITICAL_SECTION(mutex1);
+ ENTER_CRITICAL_SECTION(mutex2);
+#ifdef DEBUG_LOCKORDER
+ BOOST_CHECK_EXCEPTION(LEAVE_CRITICAL_SECTION(mutex1), std::logic_error, HasReason("mutex1 was not most recent critical section locked"));
+#endif // DEBUG_LOCKORDER
+ LEAVE_CRITICAL_SECTION(mutex2);
+ LEAVE_CRITICAL_SECTION(mutex1);
+ BOOST_CHECK(LockStackEmpty());
+}
} // namespace
BOOST_FIXTURE_TEST_SUITE(sync_tests, BasicTestingSetup)
@@ -55,4 +101,48 @@ BOOST_AUTO_TEST_CASE(potential_deadlock_detected)
#endif
}
+/* Double lock would produce an undefined behavior. Thus, we only do that if
+ * DEBUG_LOCKORDER is activated to detect it. We don't want non-DEBUG_LOCKORDER
+ * build to produce tests that exhibit known undefined behavior. */
+#ifdef DEBUG_LOCKORDER
+BOOST_AUTO_TEST_CASE(double_lock_mutex)
+{
+ TestDoubleLock<Mutex>(true /* should throw */);
+}
+
+BOOST_AUTO_TEST_CASE(double_lock_boost_mutex)
+{
+ TestDoubleLock<boost::mutex>(true /* should throw */);
+}
+
+BOOST_AUTO_TEST_CASE(double_lock_recursive_mutex)
+{
+ TestDoubleLock<RecursiveMutex>(false /* should not throw */);
+}
+#endif /* DEBUG_LOCKORDER */
+
+BOOST_AUTO_TEST_CASE(inconsistent_lock_order_detected)
+{
+#ifdef DEBUG_LOCKORDER
+ bool prev = g_debug_lockorder_abort;
+ g_debug_lockorder_abort = false;
+#endif // DEBUG_LOCKORDER
+
+ RecursiveMutex rmutex1, rmutex2;
+ TestInconsistentLockOrderDetected(rmutex1, rmutex2);
+ // By checking lock order consistency (CheckLastCritical) before any unlocking (LeaveCritical)
+ // the lock tracking data must not have been broken by exception.
+ TestInconsistentLockOrderDetected(rmutex1, rmutex2);
+
+ Mutex mutex1, mutex2;
+ TestInconsistentLockOrderDetected(mutex1, mutex2);
+ // By checking lock order consistency (CheckLastCritical) before any unlocking (LeaveCritical)
+ // the lock tracking data must not have been broken by exception.
+ TestInconsistentLockOrderDetected(mutex1, mutex2);
+
+#ifdef DEBUG_LOCKORDER
+ g_debug_lockorder_abort = prev;
+#endif // DEBUG_LOCKORDER
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index b7ee280336..1f520074b1 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -305,7 +305,7 @@ BOOST_AUTO_TEST_CASE(test_Get)
t1.vout[0].nValue = 90*CENT;
t1.vout[0].scriptPubKey << OP_1;
- BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins));
+ BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins, false));
}
static void CreateCreditAndSpend(const FillableSigningProvider& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true)
diff --git a/src/test/util/logging.h b/src/test/util/logging.h
index 1fcf7ca305..a49f9a7292 100644
--- a/src/test/util/logging.h
+++ b/src/test/util/logging.h
@@ -32,7 +32,7 @@ class DebugLogHelper
void check_found();
public:
- DebugLogHelper(std::string message, MatchFn match = [](const std::string*){ return true; });
+ explicit DebugLogHelper(std::string message, MatchFn match = [](const std::string*){ return true; });
~DebugLogHelper() { check_found(); }
};
diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp
index 09f2f1807f..847a490e03 100644
--- a/src/test/util/net.cpp
+++ b/src/test/util/net.cpp
@@ -7,9 +7,9 @@
#include <chainparams.h>
#include <net.h>
-void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const
+void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const
{
- assert(node.ReceiveMsgBytes(pch, nBytes, complete));
+ assert(node.ReceiveMsgBytes(msg_bytes, complete));
if (complete) {
size_t nSizeAdded = 0;
auto it(node.vRecvMsg.begin());
@@ -29,11 +29,11 @@ void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned
bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const
{
- std::vector<unsigned char> ser_msg_header;
+ std::vector<uint8_t> ser_msg_header;
node.m_serializer->prepareForTransport(ser_msg, ser_msg_header);
bool complete;
- NodeReceiveMsgBytes(node, (const char*)ser_msg_header.data(), ser_msg_header.size(), complete);
- NodeReceiveMsgBytes(node, (const char*)ser_msg.data.data(), ser_msg.data.size(), complete);
+ NodeReceiveMsgBytes(node, ser_msg_header, complete);
+ NodeReceiveMsgBytes(node, ser_msg.data, complete);
return complete;
}
diff --git a/src/test/util/net.h b/src/test/util/net.h
index ca8cb7fad5..1208e92762 100644
--- a/src/test/util/net.h
+++ b/src/test/util/net.h
@@ -25,7 +25,7 @@ struct ConnmanTestMsg : public CConnman {
void ProcessMessagesOnce(CNode& node) { m_msgproc->ProcessMessages(&node, flagInterruptMsgProc); }
- void NodeReceiveMsgBytes(CNode& node, const char* pch, unsigned int nBytes, bool& complete) const;
+ void NodeReceiveMsgBytes(CNode& node, Span<const uint8_t> msg_bytes, bool& complete) const;
bool ReceiveMsgFrom(CNode& node, CSerializedNetMsg& ser_msg) const;
};
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 2d3137e1e2..db8b43d039 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -16,6 +16,7 @@
#include <net.h>
#include <net_processing.h>
#include <noui.h>
+#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
#include <rpc/register.h>
@@ -124,41 +125,21 @@ BasicTestingSetup::~BasicTestingSetup()
ECC_Stop();
}
-TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
+ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
: BasicTestingSetup(chainName, extra_args)
{
- const CChainParams& chainparams = Params();
- // Ideally we'd move all the RPC tests to the functional testing framework
- // instead of unit tests, but for now we need these here.
- RegisterAllCoreRPCCommands(tableRPC);
-
- m_node.scheduler = MakeUnique<CScheduler>();
-
// We have to run a scheduler thread to prevent ActivateBestChain
// from blocking due to queue overrun.
+ m_node.scheduler = MakeUnique<CScheduler>();
threadGroup.create_thread([&] { TraceThread("scheduler", [&] { m_node.scheduler->serviceQueue(); }); });
GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler);
pblocktree.reset(new CBlockTreeDB(1 << 20, true));
- m_node.mempool = MakeUnique<CTxMemPool>(&::feeEstimator);
- m_node.mempool->setSanityCheck(1.0);
+ m_node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
+ m_node.mempool = std::make_unique<CTxMemPool>(m_node.fee_estimator.get(), 1);
m_node.chainman = &::g_chainman;
- m_node.chainman->InitializeChainstate(*m_node.mempool);
- ::ChainstateActive().InitCoinsDB(
- /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
- assert(!::ChainstateActive().CanFlushToDisk());
- ::ChainstateActive().InitCoinsCache(1 << 23);
- assert(::ChainstateActive().CanFlushToDisk());
- if (!LoadGenesisBlock(chainparams)) {
- throw std::runtime_error("LoadGenesisBlock failed.");
- }
-
- BlockValidationState state;
- if (!ActivateBestChain(state, chainparams)) {
- throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
- }
// Start script-checking threads. Set g_parallel_script_checks to true so they are used.
constexpr int script_check_threads = 2;
@@ -166,18 +147,9 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
}
g_parallel_script_checks = true;
-
- m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
- m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
- m_node.peerman = MakeUnique<PeerManager>(chainparams, *m_node.connman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
- {
- CConnman::Options options;
- options.m_msgproc = m_node.peerman.get();
- m_node.connman->Init(options);
- }
}
-TestingSetup::~TestingSetup()
+ChainTestingSetup::~ChainTestingSetup()
{
if (m_node.scheduler) m_node.scheduler->stop();
threadGroup.interrupt_all();
@@ -195,6 +167,41 @@ TestingSetup::~TestingSetup()
pblocktree.reset();
}
+TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const char*>& extra_args)
+ : ChainTestingSetup(chainName, extra_args)
+{
+ const CChainParams& chainparams = Params();
+ // Ideally we'd move all the RPC tests to the functional testing framework
+ // instead of unit tests, but for now we need these here.
+ RegisterAllCoreRPCCommands(tableRPC);
+
+ m_node.chainman->InitializeChainstate(*m_node.mempool);
+ ::ChainstateActive().InitCoinsDB(
+ /* cache_size_bytes */ 1 << 23, /* in_memory */ true, /* should_wipe */ false);
+ assert(!::ChainstateActive().CanFlushToDisk());
+ ::ChainstateActive().InitCoinsCache(1 << 23);
+ assert(::ChainstateActive().CanFlushToDisk());
+ if (!LoadGenesisBlock(chainparams)) {
+ throw std::runtime_error("LoadGenesisBlock failed.");
+ }
+
+ BlockValidationState state;
+ if (!ActivateBestChain(state, chainparams)) {
+ throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
+ }
+
+ m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
+ m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
+ m_node.peerman = std::make_unique<PeerManager>(chainparams, *m_node.connman, m_node.banman.get(),
+ *m_node.scheduler, *m_node.chainman, *m_node.mempool,
+ false);
+ {
+ CConnman::Options options;
+ options.m_msgproc = m_node.peerman.get();
+ m_node.connman->Init(options);
+ }
+}
+
TestChain100Setup::TestChain100Setup()
{
// Generate a 100-block chain:
diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h
index a09c8c122d..0498e7d182 100644
--- a/src/test/util/setup_common.h
+++ b/src/test/util/setup_common.h
@@ -11,6 +11,7 @@
#include <node/context.h>
#include <pubkey.h>
#include <random.h>
+#include <stdexcept>
#include <txmempool.h>
#include <util/check.h>
#include <util/string.h>
@@ -82,14 +83,21 @@ private:
const fs::path m_path_root;
};
-/** Testing setup that configures a complete environment.
- * Included are coins database, script check threads setup.
+/** Testing setup that performs all steps up until right before
+ * ChainstateManager gets initialized. Meant for testing ChainstateManager
+ * initialization behaviour.
*/
-struct TestingSetup : public BasicTestingSetup {
+struct ChainTestingSetup : public BasicTestingSetup {
boost::thread_group threadGroup;
+ explicit ChainTestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
+ ~ChainTestingSetup();
+};
+
+/** Testing setup that configures a complete environment.
+ */
+struct TestingSetup : public ChainTestingSetup {
explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN, const std::vector<const char*>& extra_args = {});
- ~TestingSetup();
};
/** Identical to TestingSetup, but chain set to regtest */
@@ -158,13 +166,15 @@ std::ostream& operator<<(std::ostream& os, const uint256& num);
* Use as
* BOOST_CHECK_EXCEPTION(code that throws, exception type, HasReason("foo"));
*/
-class HasReason {
+class HasReason
+{
public:
explicit HasReason(const std::string& reason) : m_reason(reason) {}
- template <typename E>
- bool operator() (const E& e) const {
+ bool operator()(const std::exception& e) const
+ {
return std::string(e.what()).find(m_reason) != std::string::npos;
};
+
private:
const std::string m_reason;
};
diff --git a/src/test/util/validation.cpp b/src/test/util/validation.cpp
new file mode 100644
index 0000000000..1aed492c3c
--- /dev/null
+++ b/src/test/util/validation.cpp
@@ -0,0 +1,22 @@
+// 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.
+
+#include <test/util/validation.h>
+
+#include <util/check.h>
+#include <util/time.h>
+#include <validation.h>
+
+void TestChainState::ResetIbd()
+{
+ m_cached_finished_ibd = false;
+ assert(IsInitialBlockDownload());
+}
+
+void TestChainState::JumpOutOfIbd()
+{
+ Assert(IsInitialBlockDownload());
+ m_cached_finished_ibd = true;
+ Assert(!IsInitialBlockDownload());
+}
diff --git a/src/test/util/validation.h b/src/test/util/validation.h
new file mode 100644
index 0000000000..b13aa0be60
--- /dev/null
+++ b/src/test/util/validation.h
@@ -0,0 +1,17 @@
+// 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.
+
+#ifndef BITCOIN_TEST_UTIL_VALIDATION_H
+#define BITCOIN_TEST_UTIL_VALIDATION_H
+
+#include <validation.h>
+
+struct TestChainState : public CChainState {
+ /** Reset the ibd cache to its initial state */
+ void ResetIbd();
+ /** Toggle IsInitialBlockDownload from true to false */
+ void JumpOutOfIbd();
+};
+
+#endif // BITCOIN_TEST_UTIL_VALIDATION_H
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 241c56934e..a9ef0f73cc 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -23,6 +23,7 @@
#include <array>
#include <stdint.h>
+#include <string.h>
#include <thread>
#include <univalue.h>
#include <utility>
@@ -35,6 +36,8 @@
#include <boost/test/unit_test.hpp>
+using namespace std::literals;
+
/* defined in logging.cpp */
namespace BCLog {
std::string LogEscapeMessage(const std::string& str);
@@ -42,6 +45,28 @@ namespace BCLog {
BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
+BOOST_AUTO_TEST_CASE(util_datadir)
+{
+ ClearDatadirCache();
+ const fs::path dd_norm = GetDataDir();
+
+ gArgs.ForceSetArg("-datadir", dd_norm.string() + "/");
+ ClearDatadirCache();
+ BOOST_CHECK_EQUAL(dd_norm, GetDataDir());
+
+ gArgs.ForceSetArg("-datadir", dd_norm.string() + "/.");
+ ClearDatadirCache();
+ BOOST_CHECK_EQUAL(dd_norm, GetDataDir());
+
+ gArgs.ForceSetArg("-datadir", dd_norm.string() + "/./");
+ ClearDatadirCache();
+ BOOST_CHECK_EQUAL(dd_norm, GetDataDir());
+
+ gArgs.ForceSetArg("-datadir", dd_norm.string() + "/.//");
+ ClearDatadirCache();
+ BOOST_CHECK_EQUAL(dd_norm, GetDataDir());
+}
+
BOOST_AUTO_TEST_CASE(util_check)
{
// Check that Assert can forward
@@ -206,7 +231,7 @@ public:
Optional<std::vector<std::string>> list_value;
const char* error = nullptr;
- Expect(util::SettingsValue s) : setting(std::move(s)) {}
+ explicit Expect(util::SettingsValue s) : setting(std::move(s)) {}
Expect& DefaultString() { default_string = true; return *this; }
Expect& DefaultInt() { default_int = true; return *this; }
Expect& DefaultBool() { default_bool = true; return *this; }
@@ -1235,9 +1260,9 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK(!ParseMoney("-1", ret));
// Parsing strings with embedded NUL characters should fail
- BOOST_CHECK(!ParseMoney(std::string("\0-1", 3), ret));
- BOOST_CHECK(!ParseMoney(std::string("\01", 2), ret));
- BOOST_CHECK(!ParseMoney(std::string("1\0", 2), ret));
+ BOOST_CHECK(!ParseMoney("\0-1"s, ret));
+ BOOST_CHECK(!ParseMoney("\0" "1"s, ret));
+ BOOST_CHECK(!ParseMoney("1\0"s, ret));
}
BOOST_AUTO_TEST_CASE(util_IsHex)
@@ -1398,10 +1423,18 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32)
BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
+ BOOST_CHECK(ParseInt32("00000000000000001234", &n) && n == 1234);
+ BOOST_CHECK(ParseInt32("-00000000000000001234", &n) && n == -1234);
+ BOOST_CHECK(ParseInt32("00000000000000000000", &n) && n == 0);
+ BOOST_CHECK(ParseInt32("-00000000000000000000", &n) && n == 0);
// Invalid values
BOOST_CHECK(!ParseInt32("", &n));
BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
BOOST_CHECK(!ParseInt32("1 ", &n));
+ BOOST_CHECK(!ParseInt32("++1", &n));
+ BOOST_CHECK(!ParseInt32("+-1", &n));
+ BOOST_CHECK(!ParseInt32("-+1", &n));
+ BOOST_CHECK(!ParseInt32("--1", &n));
BOOST_CHECK(!ParseInt32("1a", &n));
BOOST_CHECK(!ParseInt32("aap", &n));
BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
@@ -1457,10 +1490,19 @@ BOOST_AUTO_TEST_CASE(test_ParseUInt32)
BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
BOOST_CHECK(ParseUInt32("2147483648", &n) && n == (uint32_t)2147483648);
BOOST_CHECK(ParseUInt32("4294967295", &n) && n == (uint32_t)4294967295);
+ BOOST_CHECK(ParseUInt32("+1234", &n) && n == 1234);
+ BOOST_CHECK(ParseUInt32("00000000000000001234", &n) && n == 1234);
+ BOOST_CHECK(ParseUInt32("00000000000000000000", &n) && n == 0);
// Invalid values
+ BOOST_CHECK(!ParseUInt32("-00000000000000000000", &n));
BOOST_CHECK(!ParseUInt32("", &n));
BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
BOOST_CHECK(!ParseUInt32(" -1", &n));
+ BOOST_CHECK(!ParseUInt32("++1", &n));
+ BOOST_CHECK(!ParseUInt32("+-1", &n));
+ BOOST_CHECK(!ParseUInt32("-+1", &n));
+ BOOST_CHECK(!ParseUInt32("--1", &n));
+ BOOST_CHECK(!ParseUInt32("-1", &n));
BOOST_CHECK(!ParseUInt32("1 ", &n));
BOOST_CHECK(!ParseUInt32("1a", &n));
BOOST_CHECK(!ParseUInt32("aap", &n));
@@ -1571,9 +1613,9 @@ BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
std::vector<std::string> comments2;
comments2.push_back(std::string("comment1"));
comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
- BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/"));
- BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/"));
- BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; Comment2; .,_?@-; )/"));
+ BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:9.99.0/"));
+ BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:9.99.0(comment1)/"));
+ BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:9.99.0(comment1; Comment2; .,_?@-; )/"));
}
BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
@@ -1818,7 +1860,7 @@ BOOST_AUTO_TEST_CASE(test_Capitalize)
BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");
}
-static std::string SpanToStr(Span<const char>& span)
+static std::string SpanToStr(const Span<const char>& span)
{
return std::string(span.begin(), span.end());
}
diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp
index 36badafc4e..75939e0140 100644
--- a/src/test/validation_chainstatemanager_tests.cpp
+++ b/src/test/validation_chainstatemanager_tests.cpp
@@ -15,15 +15,16 @@
#include <boost/test/unit_test.hpp>
-BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup)
//! Basic tests for ChainstateManager.
//!
//! First create a legacy (IBD) chainstate, then create a snapshot chainstate.
BOOST_AUTO_TEST_CASE(chainstatemanager)
{
- ChainstateManager manager;
- CTxMemPool mempool;
+ ChainstateManager& manager = *m_node.chainman;
+ CTxMemPool& mempool = *m_node.mempool;
+
std::vector<CChainState*> chainstates;
const CChainParams& chainparams = Params();
@@ -104,8 +105,9 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
//! Test rebalancing the caches associated with each chainstate.
BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
- ChainstateManager manager;
- CTxMemPool mempool;
+ ChainstateManager& manager = *m_node.chainman;
+ CTxMemPool& mempool = *m_node.mempool;
+
size_t max_cache = 10000;
manager.m_total_coinsdb_cache = max_cache;
manager.m_total_coinstip_cache = max_cache;
@@ -122,6 +124,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
LOCK(::cs_main);
c1.InitCoinsCache(1 << 23);
+ BOOST_REQUIRE(c1.LoadGenesisBlock(Params()));
c1.CoinsTip().SetBestBlock(InsecureRand256());
manager.MaybeRebalanceCaches();
}
@@ -139,6 +142,7 @@ BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
{
LOCK(::cs_main);
c2.InitCoinsCache(1 << 23);
+ BOOST_REQUIRE(c2.LoadGenesisBlock(Params()));
c2.CoinsTip().SetBestBlock(InsecureRand256());
manager.MaybeRebalanceCaches();
}
diff --git a/src/tinyformat.h b/src/tinyformat.h
index be63f2d5d8..bc893ccda5 100644
--- a/src/tinyformat.h
+++ b/src/tinyformat.h
@@ -514,7 +514,7 @@ class FormatArg
{ }
template<typename T>
- FormatArg(const T& value)
+ explicit FormatArg(const T& value)
: m_value(static_cast<const void*>(&value)),
m_formatImpl(&formatImpl<T>),
m_toIntImpl(&toIntImpl<T>)
@@ -970,7 +970,7 @@ class FormatListN : public FormatList
public:
#ifdef TINYFORMAT_USE_VARIADIC_TEMPLATES
template<typename... Args>
- FormatListN(const Args&... args)
+ explicit FormatListN(const Args&... args)
: FormatList(&m_formatterStore[0], N),
m_formatterStore { FormatArg(args)... }
{ static_assert(sizeof...(args) == N, "Number of args must be N"); }
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 8ebe3d750d..9d91f42b1b 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -7,6 +7,7 @@
#include <chainparams.h>
#include <chainparamsbase.h>
+#include <compat.h>
#include <crypto/hmac_sha256.h>
#include <net.h>
#include <netaddress.h>
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 0c2b731967..d18182c07d 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -331,15 +331,10 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee,
assert(int(nSigOpCostWithAncestors) >= 0);
}
-CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator)
- : nTransactionsUpdated(0), minerPolicyEstimator(estimator), m_epoch(0), m_has_epoch_guard(false)
+CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator, int check_ratio)
+ : m_check_ratio(check_ratio), minerPolicyEstimator(estimator)
{
_clear(); //lock free clear
-
- // Sanity checks off by default for performance, because otherwise
- // accepting transactions becomes O(N^2) where N is the number
- // of transactions in the pool
- nCheckFrequency = 0;
}
bool CTxMemPool::isSpent(const COutPoint& outpoint) const
@@ -523,7 +518,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
if (it2 != mapTx.end())
continue;
const Coin &coin = pcoins->AccessCoin(txin.prevout);
- if (nCheckFrequency != 0) assert(!coin.IsSpent());
+ if (m_check_ratio != 0) assert(!coin.IsSpent());
if (coin.IsSpent() || (coin.IsCoinBase() && ((signed long)nMemPoolHeight) - coin.nHeight < COINBASE_MATURITY)) {
txToRemove.insert(it);
break;
@@ -619,13 +614,11 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m
void CTxMemPool::check(const CCoinsViewCache *pcoins) const
{
- LOCK(cs);
- if (nCheckFrequency == 0)
- return;
+ if (m_check_ratio == 0) return;
- if (GetRand(std::numeric_limits<uint32_t>::max()) >= nCheckFrequency)
- return;
+ if (GetRand(m_check_ratio) >= 1) return;
+ LOCK(cs);
LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
uint64_t checkTotal = 0;
diff --git a/src/txmempool.h b/src/txmempool.h
index f513f14af6..15797cbc00 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -488,8 +488,8 @@ public:
class CTxMemPool
{
private:
- uint32_t nCheckFrequency GUARDED_BY(cs); //!< Value n means that n times in 2^32 we check.
- std::atomic<unsigned int> nTransactionsUpdated; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
+ const int m_check_ratio; //!< Value n means that 1 times in n we check.
+ std::atomic<unsigned int> nTransactionsUpdated{0}; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
CBlockPolicyEstimator* minerPolicyEstimator;
uint64_t totalTxSize; //!< sum of all mempool tx's virtual sizes. Differs from serialized tx size since witness data is discounted. Defined in BIP 141.
@@ -498,8 +498,8 @@ private:
mutable int64_t lastRollingFeeUpdate;
mutable bool blockSinceLastRollingFeeBump;
mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially
- mutable uint64_t m_epoch;
- mutable bool m_has_epoch_guard;
+ mutable uint64_t m_epoch{0};
+ mutable bool m_has_epoch_guard{false};
// In-memory counter for external mempool tracking purposes.
// This number is incremented once every time a transaction
@@ -601,8 +601,14 @@ public:
std::map<uint256, CAmount> mapDeltas;
/** 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);
+ explicit CTxMemPool(CBlockPolicyEstimator* estimator = nullptr, int check_ratio = 0);
/**
* If sanity-checking is turned on, check makes sure the pool is
@@ -611,7 +617,6 @@ public:
* check does nothing.
*/
void check(const CCoinsViewCache *pcoins) const;
- void setSanityCheck(double dFrequency = 1.0) { LOCK(cs); nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); }
// addUnchecked must updated state for all ancestors of a given transaction,
// to track size/count of descendant transactions. First version of
@@ -850,7 +855,7 @@ public:
class EpochGuard {
const CTxMemPool& pool;
public:
- EpochGuard(const CTxMemPool& in);
+ explicit EpochGuard(const CTxMemPool& in);
~EpochGuard();
};
// N.B. GetFreshEpoch modifies mutable state via the EpochGuard construction
diff --git a/src/txrequest.cpp b/src/txrequest.cpp
index 494786c201..e54c073328 100644
--- a/src/txrequest.cpp
+++ b/src/txrequest.cpp
@@ -69,32 +69,40 @@ struct Announcement {
/** Whether this is a wtxid request. */
const bool m_is_wtxid : 1;
- /** What state this announcement is in. */
- State m_state : 3;
+ /** What state this announcement is in.
+ * This is a uint8_t instead of a State to silence a GCC warning in versions prior to 8.4 and 9.3.
+ * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414 */
+ uint8_t m_state : 3;
+
+ /** Convert m_state to a State enum. */
+ State GetState() const { return static_cast<State>(m_state); }
+
+ /** Convert a State enum to a uint8_t and store it in m_state. */
+ void SetState(State state) { m_state = static_cast<uint8_t>(state); }
/** Whether this announcement is selected. There can be at most 1 selected peer per txhash. */
bool IsSelected() const
{
- return m_state == State::CANDIDATE_BEST || m_state == State::REQUESTED;
+ return GetState() == State::CANDIDATE_BEST || GetState() == State::REQUESTED;
}
/** Whether this announcement is waiting for a certain time to pass. */
bool IsWaiting() const
{
- return m_state == State::REQUESTED || m_state == State::CANDIDATE_DELAYED;
+ return GetState() == State::REQUESTED || GetState() == State::CANDIDATE_DELAYED;
}
/** Whether this announcement can feasibly be selected if the current IsSelected() one disappears. */
bool IsSelectable() const
{
- return m_state == State::CANDIDATE_READY || m_state == State::CANDIDATE_BEST;
+ return GetState() == State::CANDIDATE_READY || GetState() == State::CANDIDATE_BEST;
}
/** Construct a new announcement from scratch, initially in CANDIDATE_DELAYED state. */
Announcement(const GenTxid& gtxid, NodeId peer, bool preferred, std::chrono::microseconds reqtime,
SequenceNumber sequence) :
m_txhash(gtxid.GetHash()), m_time(reqtime), m_peer(peer), m_sequence(sequence), m_preferred(preferred),
- m_is_wtxid(gtxid.IsWtxid()), m_state(State::CANDIDATE_DELAYED) {}
+ m_is_wtxid(gtxid.IsWtxid()), m_state(static_cast<uint8_t>(State::CANDIDATE_DELAYED)) {}
};
//! Type alias for priorities.
@@ -143,7 +151,7 @@ struct ByPeerViewExtractor
using result_type = ByPeerView;
result_type operator()(const Announcement& ann) const
{
- return ByPeerView{ann.m_peer, ann.m_state == State::CANDIDATE_BEST, ann.m_txhash};
+ return ByPeerView{ann.m_peer, ann.GetState() == State::CANDIDATE_BEST, ann.m_txhash};
}
};
@@ -162,12 +170,12 @@ using ByTxHashView = std::tuple<const uint256&, State, Priority>;
class ByTxHashViewExtractor {
const PriorityComputer& m_computer;
public:
- ByTxHashViewExtractor(const PriorityComputer& computer) : m_computer(computer) {}
+ explicit ByTxHashViewExtractor(const PriorityComputer& computer) : m_computer(computer) {}
using result_type = ByTxHashView;
result_type operator()(const Announcement& ann) const
{
- const Priority prio = (ann.m_state == State::CANDIDATE_READY) ? m_computer(ann) : 0;
- return ByTxHashView{ann.m_txhash, ann.m_state, prio};
+ const Priority prio = (ann.GetState() == State::CANDIDATE_READY) ? m_computer(ann) : 0;
+ return ByTxHashView{ann.m_txhash, ann.GetState(), prio};
}
};
@@ -261,8 +269,8 @@ std::unordered_map<NodeId, PeerInfo> RecomputePeerInfo(const Index& index)
for (const Announcement& ann : index) {
PeerInfo& info = ret[ann.m_peer];
++info.m_total;
- info.m_requested += (ann.m_state == State::REQUESTED);
- info.m_completed += (ann.m_state == State::COMPLETED);
+ info.m_requested += (ann.GetState() == State::REQUESTED);
+ info.m_completed += (ann.GetState() == State::COMPLETED);
}
return ret;
}
@@ -274,15 +282,15 @@ std::map<uint256, TxHashInfo> ComputeTxHashInfo(const Index& index, const Priori
for (const Announcement& ann : index) {
TxHashInfo& info = ret[ann.m_txhash];
// Classify how many announcements of each state we have for this txhash.
- info.m_candidate_delayed += (ann.m_state == State::CANDIDATE_DELAYED);
- info.m_candidate_ready += (ann.m_state == State::CANDIDATE_READY);
- info.m_candidate_best += (ann.m_state == State::CANDIDATE_BEST);
- info.m_requested += (ann.m_state == State::REQUESTED);
+ info.m_candidate_delayed += (ann.GetState() == State::CANDIDATE_DELAYED);
+ info.m_candidate_ready += (ann.GetState() == State::CANDIDATE_READY);
+ info.m_candidate_best += (ann.GetState() == State::CANDIDATE_BEST);
+ info.m_requested += (ann.GetState() == State::REQUESTED);
// And track the priority of the best CANDIDATE_READY/CANDIDATE_BEST announcements.
- if (ann.m_state == State::CANDIDATE_BEST) {
+ if (ann.GetState() == State::CANDIDATE_BEST) {
info.m_priority_candidate_best = computer(ann);
}
- if (ann.m_state == State::CANDIDATE_READY) {
+ if (ann.GetState() == State::CANDIDATE_READY) {
info.m_priority_best_candidate_ready = std::max(info.m_priority_best_candidate_ready, computer(ann));
}
// Also keep track of which peers this txhash has an announcement for (so we can detect duplicates).
@@ -369,8 +377,8 @@ private:
Iter<Tag> Erase(Iter<Tag> it)
{
auto peerit = m_peerinfo.find(it->m_peer);
- peerit->second.m_completed -= it->m_state == State::COMPLETED;
- peerit->second.m_requested -= it->m_state == State::REQUESTED;
+ peerit->second.m_completed -= it->GetState() == State::COMPLETED;
+ peerit->second.m_requested -= it->GetState() == State::REQUESTED;
if (--peerit->second.m_total == 0) m_peerinfo.erase(peerit);
return m_index.get<Tag>().erase(it);
}
@@ -380,11 +388,11 @@ private:
void Modify(Iter<Tag> it, Modifier modifier)
{
auto peerit = m_peerinfo.find(it->m_peer);
- peerit->second.m_completed -= it->m_state == State::COMPLETED;
- peerit->second.m_requested -= it->m_state == State::REQUESTED;
+ peerit->second.m_completed -= it->GetState() == State::COMPLETED;
+ peerit->second.m_requested -= it->GetState() == State::REQUESTED;
m_index.get<Tag>().modify(it, std::move(modifier));
- peerit->second.m_completed += it->m_state == State::COMPLETED;
- peerit->second.m_requested += it->m_state == State::REQUESTED;
+ peerit->second.m_completed += it->GetState() == State::COMPLETED;
+ peerit->second.m_requested += it->GetState() == State::REQUESTED;
}
//! Convert a CANDIDATE_DELAYED announcement into a CANDIDATE_READY. If this makes it the new best
@@ -393,26 +401,26 @@ private:
void PromoteCandidateReady(Iter<ByTxHash> it)
{
assert(it != m_index.get<ByTxHash>().end());
- assert(it->m_state == State::CANDIDATE_DELAYED);
+ assert(it->GetState() == State::CANDIDATE_DELAYED);
// Convert CANDIDATE_DELAYED to CANDIDATE_READY first.
- Modify<ByTxHash>(it, [](Announcement& ann){ ann.m_state = State::CANDIDATE_READY; });
+ Modify<ByTxHash>(it, [](Announcement& ann){ ann.SetState(State::CANDIDATE_READY); });
// The following code relies on the fact that the ByTxHash is sorted by txhash, and then by state (first
// _DELAYED, then _READY, then _BEST/REQUESTED). Within the _READY announcements, the best one (highest
// priority) comes last. Thus, if an existing _BEST exists for the same txhash that this announcement may
// be preferred over, it must immediately follow the newly created _READY.
auto it_next = std::next(it);
if (it_next == m_index.get<ByTxHash>().end() || it_next->m_txhash != it->m_txhash ||
- it_next->m_state == State::COMPLETED) {
+ it_next->GetState() == State::COMPLETED) {
// This is the new best CANDIDATE_READY, and there is no IsSelected() announcement for this txhash
// already.
- Modify<ByTxHash>(it, [](Announcement& ann){ ann.m_state = State::CANDIDATE_BEST; });
- } else if (it_next->m_state == State::CANDIDATE_BEST) {
+ Modify<ByTxHash>(it, [](Announcement& ann){ ann.SetState(State::CANDIDATE_BEST); });
+ } else if (it_next->GetState() == State::CANDIDATE_BEST) {
Priority priority_old = m_computer(*it_next);
Priority priority_new = m_computer(*it);
if (priority_new > priority_old) {
// There is a CANDIDATE_BEST announcement already, but this one is better.
- Modify<ByTxHash>(it_next, [](Announcement& ann){ ann.m_state = State::CANDIDATE_READY; });
- Modify<ByTxHash>(it, [](Announcement& ann){ ann.m_state = State::CANDIDATE_BEST; });
+ Modify<ByTxHash>(it_next, [](Announcement& ann){ ann.SetState(State::CANDIDATE_READY); });
+ Modify<ByTxHash>(it, [](Announcement& ann){ ann.SetState(State::CANDIDATE_BEST); });
}
}
}
@@ -427,19 +435,19 @@ private:
auto it_prev = std::prev(it);
// The next best CANDIDATE_READY, if any, immediately precedes the REQUESTED or CANDIDATE_BEST
// announcement in the ByTxHash index.
- if (it_prev->m_txhash == it->m_txhash && it_prev->m_state == State::CANDIDATE_READY) {
+ if (it_prev->m_txhash == it->m_txhash && it_prev->GetState() == State::CANDIDATE_READY) {
// If one such CANDIDATE_READY exists (for this txhash), convert it to CANDIDATE_BEST.
- Modify<ByTxHash>(it_prev, [](Announcement& ann){ ann.m_state = State::CANDIDATE_BEST; });
+ Modify<ByTxHash>(it_prev, [](Announcement& ann){ ann.SetState(State::CANDIDATE_BEST); });
}
}
- Modify<ByTxHash>(it, [new_state](Announcement& ann){ ann.m_state = new_state; });
+ Modify<ByTxHash>(it, [new_state](Announcement& ann){ ann.SetState(new_state); });
}
//! Check if 'it' is the only announcement for a given txhash that isn't COMPLETED.
bool IsOnlyNonCompleted(Iter<ByTxHash> it)
{
assert(it != m_index.get<ByTxHash>().end());
- assert(it->m_state != State::COMPLETED); // Not allowed to call this on COMPLETED announcements.
+ assert(it->GetState() != State::COMPLETED); // Not allowed to call this on COMPLETED announcements.
// This announcement has a predecessor that belongs to the same txhash. Due to ordering, and the
// fact that 'it' is not COMPLETED, its predecessor cannot be COMPLETED here.
@@ -447,7 +455,7 @@ private:
// This announcement has a successor that belongs to the same txhash, and is not COMPLETED.
if (std::next(it) != m_index.get<ByTxHash>().end() && std::next(it)->m_txhash == it->m_txhash &&
- std::next(it)->m_state != State::COMPLETED) return false;
+ std::next(it)->GetState() != State::COMPLETED) return false;
return true;
}
@@ -460,7 +468,7 @@ private:
assert(it != m_index.get<ByTxHash>().end());
// Nothing to be done if it's already COMPLETED.
- if (it->m_state == State::COMPLETED) return true;
+ if (it->GetState() == State::COMPLETED) return true;
if (IsOnlyNonCompleted(it)) {
// This is the last non-COMPLETED announcement for this txhash. Delete all.
@@ -490,9 +498,9 @@ private:
// and convert them to CANDIDATE_READY and COMPLETED respectively.
while (!m_index.empty()) {
auto it = m_index.get<ByTime>().begin();
- if (it->m_state == State::CANDIDATE_DELAYED && it->m_time <= now) {
+ if (it->GetState() == State::CANDIDATE_DELAYED && it->m_time <= now) {
PromoteCandidateReady(m_index.project<ByTxHash>(it));
- } else if (it->m_state == State::REQUESTED && it->m_time <= now) {
+ } else if (it->GetState() == State::REQUESTED && it->m_time <= now) {
if (expired) expired->emplace_back(it->m_peer, ToGenTxid(*it));
MakeCompleted(m_index.project<ByTxHash>(it));
} else {
@@ -514,7 +522,7 @@ private:
}
public:
- Impl(bool deterministic) :
+ explicit Impl(bool deterministic) :
m_computer(deterministic),
// Explicitly initialize m_index as we need to pass a reference to m_computer to ByTxHashViewExtractor.
m_index(boost::make_tuple(
@@ -596,7 +604,7 @@ public:
std::vector<const Announcement*> selected;
auto it_peer = m_index.get<ByPeer>().lower_bound(ByPeerView{peer, true, uint256::ZERO});
while (it_peer != m_index.get<ByPeer>().end() && it_peer->m_peer == peer &&
- it_peer->m_state == State::CANDIDATE_BEST) {
+ it_peer->GetState() == State::CANDIDATE_BEST) {
selected.emplace_back(&*it_peer);
++it_peer;
}
@@ -625,8 +633,8 @@ public:
// returned by GetRequestable always correspond to CANDIDATE_BEST announcements).
it = m_index.get<ByPeer>().find(ByPeerView{peer, false, txhash});
- if (it == m_index.get<ByPeer>().end() || (it->m_state != State::CANDIDATE_DELAYED &&
- it->m_state != State::CANDIDATE_READY)) {
+ if (it == m_index.get<ByPeer>().end() || (it->GetState() != State::CANDIDATE_DELAYED &&
+ it->GetState() != State::CANDIDATE_READY)) {
// There is no CANDIDATE announcement tracked for this peer, so we have nothing to do. Either this
// txhash wasn't tracked at all (and the caller should have called ReceivedInv), or it was already
// requested and/or completed for other reasons and this is just a superfluous RequestedTx call.
@@ -638,24 +646,24 @@ public:
// other CANDIDATE_BEST or REQUESTED can exist.
auto it_old = m_index.get<ByTxHash>().lower_bound(ByTxHashView{txhash, State::CANDIDATE_BEST, 0});
if (it_old != m_index.get<ByTxHash>().end() && it_old->m_txhash == txhash) {
- if (it_old->m_state == State::CANDIDATE_BEST) {
+ if (it_old->GetState() == State::CANDIDATE_BEST) {
// The data structure's invariants require that there can be at most one CANDIDATE_BEST or one
// REQUESTED announcement per txhash (but not both simultaneously), so we have to convert any
// existing CANDIDATE_BEST to another CANDIDATE_* when constructing another REQUESTED.
// It doesn't matter whether we pick CANDIDATE_READY or _DELAYED here, as SetTimePoint()
// will correct it at GetRequestable() time. If time only goes forward, it will always be
// _READY, so pick that to avoid extra work in SetTimePoint().
- Modify<ByTxHash>(it_old, [](Announcement& ann) { ann.m_state = State::CANDIDATE_READY; });
- } else if (it_old->m_state == State::REQUESTED) {
+ Modify<ByTxHash>(it_old, [](Announcement& ann) { ann.SetState(State::CANDIDATE_READY); });
+ } else if (it_old->GetState() == State::REQUESTED) {
// As we're no longer waiting for a response to the previous REQUESTED announcement, convert it
// to COMPLETED. This also helps guaranteeing progress.
- Modify<ByTxHash>(it_old, [](Announcement& ann) { ann.m_state = State::COMPLETED; });
+ Modify<ByTxHash>(it_old, [](Announcement& ann) { ann.SetState(State::COMPLETED); });
}
}
}
Modify<ByPeer>(it, [expiry](Announcement& ann) {
- ann.m_state = State::REQUESTED;
+ ann.SetState(State::REQUESTED);
ann.m_time = expiry;
});
}
diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h
index 6080516353..048e162f7d 100644
--- a/src/univalue/include/univalue.h
+++ b/src/univalue/include/univalue.h
@@ -100,6 +100,10 @@ public:
UniValue tmpVal(val_);
return push_back(tmpVal);
}
+ bool push_back(bool val_) {
+ UniValue tmpVal(val_);
+ return push_back(tmpVal);
+ }
bool push_back(int val_) {
UniValue tmpVal(val_);
return push_back(tmpVal);
@@ -129,7 +133,7 @@ public:
return pushKV(key, tmpVal);
}
bool pushKV(const std::string& key, bool val_) {
- UniValue tmpVal((bool)val_);
+ UniValue tmpVal(val_);
return pushKV(key, tmpVal);
}
bool pushKV(const std::string& key, int val_) {
diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp
index 70ccc0d08a..ccc1344836 100644
--- a/src/univalue/test/object.cpp
+++ b/src/univalue/test/object.cpp
@@ -210,19 +210,31 @@ BOOST_AUTO_TEST_CASE(univalue_array)
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));
BOOST_CHECK_EQUAL(arr.empty(), false);
- BOOST_CHECK_EQUAL(arr.size(), 9);
+ BOOST_CHECK_EQUAL(arr.size(), 10);
BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023");
+ BOOST_CHECK_EQUAL(arr[0].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy");
+ BOOST_CHECK_EQUAL(arr[1].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy");
+ BOOST_CHECK_EQUAL(arr[2].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing");
+ BOOST_CHECK_EQUAL(arr[3].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[4].getValStr(), "going");
+ BOOST_CHECK_EQUAL(arr[4].getType(), UniValue::VSTR);
BOOST_CHECK_EQUAL(arr[5].getValStr(), "400");
+ BOOST_CHECK_EQUAL(arr[5].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[6].getValStr(), "-400");
+ BOOST_CHECK_EQUAL(arr[6].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[7].getValStr(), "-401");
+ BOOST_CHECK_EQUAL(arr[7].getType(), UniValue::VNUM);
BOOST_CHECK_EQUAL(arr[8].getValStr(), "-40.1");
+ BOOST_CHECK_EQUAL(arr[8].getType(), UniValue::VNUM);
+ BOOST_CHECK_EQUAL(arr[9].getValStr(), "1");
+ BOOST_CHECK_EQUAL(arr[9].getType(), UniValue::VBOOL);
BOOST_CHECK_EQUAL(arr[999].getValStr(), "");
diff --git a/src/util/bip32.h b/src/util/bip32.h
index 347e83db9e..8f86f2aaa6 100644
--- a/src/util/bip32.h
+++ b/src/util/bip32.h
@@ -10,7 +10,7 @@
#include <vector>
/** Parse an HD keypaths like "m/7/0'/2000". */
-NODISCARD bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath);
+[[nodiscard]] bool ParseHDKeypath(const std::string& keypath_str, std::vector<uint32_t>& keypath);
/** Write HD keypaths as strings */
std::string WriteHDKeypath(const std::vector<uint32_t>& keypath);
diff --git a/src/util/check.h b/src/util/check.h
index 9edf394492..e7620d97a0 100644
--- a/src/util/check.h
+++ b/src/util/check.h
@@ -46,7 +46,7 @@ class NonFatalCheckError : public std::runtime_error
#error "Cannot compile without assertions!"
#endif
-/** Helper for Assert(). TODO remove in C++14 and replace `decltype(get_pure_r_value(val))` with `T` (templated lambda) */
+/** Helper for Assert() */
template <typename T>
T get_pure_r_value(T&& val)
{
@@ -54,6 +54,22 @@ T get_pure_r_value(T&& val)
}
/** Identity function. Abort if the value compares equal to zero */
-#define Assert(val) [&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); assert(#val && check); return std::forward<decltype(get_pure_r_value(val))>(check); }()
+#define Assert(val) ([&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); assert(#val && check); return std::forward<decltype(get_pure_r_value(val))>(check); }())
+
+/**
+ * Assume is the identity function.
+ *
+ * - Should be used to run non-fatal checks. In debug builds it behaves like
+ * Assert()/assert() to notify developers and testers about non-fatal errors.
+ * In production it doesn't warn or log anything.
+ * - For fatal errors, use Assert().
+ * - For non-fatal errors in interactive sessions (e.g. RPC or command line
+ * interfaces), CHECK_NONFATAL() might be more appropriate.
+ */
+#ifdef ABORT_ON_FAILED_ASSUME
+#define Assume(val) Assert(val)
+#else
+#define Assume(val) ((void)(val))
+#endif
#endif // BITCOIN_UTIL_CHECK_H
diff --git a/src/util/fees.cpp b/src/util/fees.cpp
index 6208a20a97..1855c0bc90 100644
--- a/src/util/fees.cpp
+++ b/src/util/fees.cpp
@@ -40,8 +40,6 @@ const std::vector<std::pair<std::string, FeeEstimateMode>>& FeeModeMap()
{"unset", FeeEstimateMode::UNSET},
{"economical", FeeEstimateMode::ECONOMICAL},
{"conservative", FeeEstimateMode::CONSERVATIVE},
- {(CURRENCY_UNIT + "/kB"), FeeEstimateMode::BTC_KB},
- {(CURRENCY_ATOM + "/B"), FeeEstimateMode::SAT_B},
};
return FEE_MODES;
}
@@ -51,6 +49,11 @@ std::string FeeModes(const std::string& delimiter)
return Join(FeeModeMap(), delimiter, [&](const std::pair<std::string, FeeEstimateMode>& i) { return i.first; });
}
+const std::string InvalidEstimateModeErrorMessage()
+{
+ return "Invalid estimate_mode parameter, must be one of: \"" + FeeModes("\", \"") + "\"";
+}
+
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode)
{
auto searchkey = ToUpper(mode_string);
diff --git a/src/util/fees.h b/src/util/fees.h
index d52046a44c..3f1c33ad9c 100644
--- a/src/util/fees.h
+++ b/src/util/fees.h
@@ -13,5 +13,6 @@ enum class FeeReason;
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
std::string StringForFeeReason(FeeReason reason);
std::string FeeModes(const std::string& delimiter);
+const std::string InvalidEstimateModeErrorMessage();
#endif // BITCOIN_UTIL_FEES_H
diff --git a/src/util/memory.h b/src/util/memory.h
index 15ecf8f80d..4d73b32869 100644
--- a/src/util/memory.h
+++ b/src/util/memory.h
@@ -10,10 +10,11 @@
#include <utility>
//! Substitute for C++14 std::make_unique.
+//! DEPRECATED use std::make_unique in new code.
template <typename T, typename... Args>
std::unique_ptr<T> MakeUnique(Args&&... args)
{
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+ return std::make_unique<T>(std::forward<Args>(args)...);
}
#endif
diff --git a/src/util/moneystr.h b/src/util/moneystr.h
index 9d2b6da0fc..da7f673cda 100644
--- a/src/util/moneystr.h
+++ b/src/util/moneystr.h
@@ -19,6 +19,6 @@
*/
std::string FormatMoney(const CAmount& n);
/** Parse an amount denoted in full coins. E.g. "0.0034" supplied on the command line. **/
-NODISCARD bool ParseMoney(const std::string& str, CAmount& nRet);
+[[nodiscard]] bool ParseMoney(const std::string& str, CAmount& nRet);
#endif // BITCOIN_UTIL_MONEYSTR_H
diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp
index 3236184b0b..f3d54a2ac9 100644
--- a/src/util/strencodings.cpp
+++ b/src/util/strencodings.cpp
@@ -280,7 +280,7 @@ std::string DecodeBase32(const std::string& str, bool* pf_invalid)
return std::string((const char*)vchRet.data(), vchRet.size());
}
-NODISCARD static bool ParsePrechecks(const std::string& str)
+[[nodiscard]] static bool ParsePrechecks(const std::string& str)
{
if (str.empty()) // No empty string allowed
return false;
diff --git a/src/util/strencodings.h b/src/util/strencodings.h
index 1a217dd12d..8ee43c620b 100644
--- a/src/util/strencodings.h
+++ b/src/util/strencodings.h
@@ -101,42 +101,42 @@ constexpr inline bool IsSpace(char c) noexcept {
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-NODISCARD bool ParseInt32(const std::string& str, int32_t *out);
+[[nodiscard]] bool ParseInt32(const std::string& str, int32_t *out);
/**
* Convert string to signed 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-NODISCARD bool ParseInt64(const std::string& str, int64_t *out);
+[[nodiscard]] bool ParseInt64(const std::string& str, int64_t *out);
/**
* Convert decimal string to unsigned 8-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-NODISCARD bool ParseUInt8(const std::string& str, uint8_t *out);
+[[nodiscard]] bool ParseUInt8(const std::string& str, uint8_t *out);
/**
* Convert decimal string to unsigned 32-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-NODISCARD bool ParseUInt32(const std::string& str, uint32_t *out);
+[[nodiscard]] bool ParseUInt32(const std::string& str, uint32_t *out);
/**
* Convert decimal string to unsigned 64-bit integer with strict parse error feedback.
* @returns true if the entire string could be parsed as valid integer,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-NODISCARD bool ParseUInt64(const std::string& str, uint64_t *out);
+[[nodiscard]] bool ParseUInt64(const std::string& str, uint64_t *out);
/**
* Convert string to double with strict parse error feedback.
* @returns true if the entire string could be parsed as valid double,
* false if not the entire string could be parsed or when overflow or underflow occurred.
*/
-NODISCARD bool ParseDouble(const std::string& str, double *out);
+[[nodiscard]] bool ParseDouble(const std::string& str, double *out);
/**
* Convert a span of bytes to a lower-case hexadecimal string.
@@ -170,7 +170,7 @@ bool TimingResistantEqual(const T& a, const T& b)
* @returns true on success, false on error.
* @note The result must be in the range (-10^18,10^18), otherwise an overflow error will trigger.
*/
-NODISCARD bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
+[[nodiscard]] bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out);
/** Convert from one power-of-2 number base to another. */
template<int frombits, int tobits, bool pad, typename O, typename I>
diff --git a/src/util/string.h b/src/util/string.h
index a0c87bd00c..5ffdc80d88 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -15,7 +15,7 @@
#include <string>
#include <vector>
-NODISCARD inline std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v")
+[[nodiscard]] inline std::string TrimString(const std::string& str, const std::string& pattern = " \f\n\r\t\v")
{
std::string::size_type front = str.find_first_not_of(pattern);
if (front == std::string::npos) {
@@ -59,7 +59,7 @@ inline std::string Join(const std::vector<std::string>& list, const std::string&
/**
* Check if a string does not contain any embedded NUL (\0) characters
*/
-NODISCARD inline bool ValidAsCString(const std::string& str) noexcept
+[[nodiscard]] inline bool ValidAsCString(const std::string& str) noexcept
{
return str.size() == strlen(str.c_str());
}
@@ -80,7 +80,7 @@ std::string ToString(const T& t)
* Check whether a container begins with the given prefix.
*/
template <typename T1, size_t PREFIX_LEN>
-NODISCARD inline bool HasPrefix(const T1& obj,
+[[nodiscard]] inline bool HasPrefix(const T1& obj,
const std::array<uint8_t, PREFIX_LEN>& prefix)
{
return obj.size() >= PREFIX_LEN &&
diff --git a/src/util/system.cpp b/src/util/system.cpp
index a411b73a16..5f30136fa2 100644
--- a/src/util/system.cpp
+++ b/src/util/system.cpp
@@ -34,6 +34,7 @@
#endif // __linux__
#include <algorithm>
+#include <cassert>
#include <fcntl.h>
#include <sched.h>
#include <sys/resource.h>
@@ -427,6 +428,14 @@ bool ArgsManager::ReadSettingsFile(std::vector<std::string>* errors)
SaveErrors(read_errors, errors);
return false;
}
+ for (const auto& setting : m_settings.rw_settings) {
+ std::string section;
+ std::string key = setting.first;
+ (void)InterpretOption(section, key, /* value */ {}); // Split setting key into section and argname
+ if (!GetArgFlags('-' + key)) {
+ LogPrintf("Ignoring unknown rw_settings value %s\n", setting.first);
+ }
+ }
return true;
}
@@ -641,10 +650,9 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
fs::path GetDefaultDataDir()
{
- // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
- // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
- // Mac: ~/Library/Application Support/Bitcoin
- // Unix: ~/.bitcoin
+ // Windows: C:\Users\Username\AppData\Roaming\Bitcoin
+ // macOS: ~/Library/Application Support/Bitcoin
+ // Unix-like: ~/.bitcoin
#ifdef WIN32
// Windows
return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
@@ -656,15 +664,28 @@ fs::path GetDefaultDataDir()
else
pathRet = fs::path(pszHome);
#ifdef MAC_OSX
- // Mac
+ // macOS
return pathRet / "Library/Application Support/Bitcoin";
#else
- // Unix
+ // Unix-like
return pathRet / ".bitcoin";
#endif
#endif
}
+namespace {
+fs::path StripRedundantLastElementsOfPath(const fs::path& path)
+{
+ auto result = path;
+ while (result.filename().string() == ".") {
+ result = result.parent_path();
+ }
+
+ assert(fs::equivalent(result, path));
+ return result;
+}
+} // namespace
+
static fs::path g_blocks_path_cache_net_specific;
static fs::path pathCached;
static fs::path pathCachedNetSpecific;
@@ -692,6 +713,7 @@ const fs::path &GetBlocksDir()
path /= BaseParams().DataDir();
path /= "blocks";
fs::create_directories(path);
+ path = StripRedundantLastElementsOfPath(path);
return path;
}
@@ -722,6 +744,7 @@ const fs::path &GetDataDir(bool fNetSpecific)
fs::create_directories(path / "wallets");
}
+ path = StripRedundantLastElementsOfPath(path);
return path;
}
diff --git a/src/util/system.h b/src/util/system.h
index 1df194ca84..2be8bb754b 100644
--- a/src/util/system.h
+++ b/src/util/system.h
@@ -60,7 +60,7 @@ bool FileCommit(FILE *file);
bool TruncateFile(FILE *file, unsigned int length);
int RaiseFileDescriptorLimit(int nMinFD);
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
-bool RenameOver(fs::path src, fs::path dest);
+[[nodiscard]] bool RenameOver(fs::path src, fs::path dest);
bool LockDirectory(const fs::path& directory, const std::string lockfile_name, bool probe_only=false);
void UnlockDirectory(const fs::path& directory, const std::string& lockfile_name);
bool DirIsWritable(const fs::path& directory);
@@ -188,7 +188,7 @@ protected:
std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args GUARDED_BY(cs_args);
std::list<SectionInfo> m_config_sections GUARDED_BY(cs_args);
- NODISCARD bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false);
+ [[nodiscard]] bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false);
/**
* Returns true if settings values from the default section should be used,
@@ -220,8 +220,8 @@ public:
*/
void SelectConfigNetwork(const std::string& network);
- NODISCARD bool ParseParameters(int argc, const char* const argv[], std::string& error);
- NODISCARD bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
+ [[nodiscard]] bool ParseParameters(int argc, const char* const argv[], std::string& error);
+ [[nodiscard]] bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
/**
* Log warnings for options in m_section_only_args when
diff --git a/src/util/time.h b/src/util/time.h
index af934e423b..c69f604dc6 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -6,9 +6,11 @@
#ifndef BITCOIN_UTIL_TIME_H
#define BITCOIN_UTIL_TIME_H
+#include <chrono>
#include <stdint.h>
#include <string>
-#include <chrono>
+
+using namespace std::chrono_literals;
void UninterruptibleSleep(const std::chrono::microseconds& n);
diff --git a/src/validation.cpp b/src/validation.cpp
index 423b93479a..2585345dee 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -22,7 +22,6 @@
#include <logging/timer.h>
#include <node/ui_interface.h>
#include <optional.h>
-#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <pow.h>
@@ -148,8 +147,6 @@ arith_uint256 nMinimumChainWork;
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
-CBlockPolicyEstimator feeEstimator;
-
// Internal stuff
namespace {
CBlockIndex* pindexBestInvalid = nullptr;
@@ -449,7 +446,7 @@ namespace {
class MemPoolAccept
{
public:
- MemPoolAccept(CTxMemPool& mempool) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&::ChainstateActive().CoinsTip(), m_pool),
+ explicit MemPoolAccept(CTxMemPool& mempool) : m_pool(mempool), m_view(&m_dummy), m_viewmempool(&::ChainstateActive().CoinsTip(), m_pool),
m_limit_ancestors(gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT)),
m_limit_ancestor_size(gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000),
m_limit_descendants(gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)),
@@ -482,7 +479,7 @@ private:
// All the intermediate state that gets passed between the various levels
// of checking a given transaction.
struct Workspace {
- Workspace(const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
+ explicit Workspace(const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
std::set<uint256> m_conflicts;
CTxMemPool::setEntries m_all_conflicting;
CTxMemPool::setEntries m_ancestors;
@@ -505,13 +502,13 @@ private:
// Run the script checks using our policy flags. As this can be slow, we should
// only invoke this on transactions that have otherwise passed policy checks.
- bool PolicyScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool PolicyScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Re-run the script checks, using consensus flags, and try to cache the
// result in the scriptcache. This should be done after
// PolicyScriptChecks(). This requires that all inputs either be in our
// utxo set or in the mempool.
- bool ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
+ bool ConsensusScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData &txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Try to add the transaction to the mempool, removing any conflicts first.
// Returns true if the transaction is in the mempool after any size
@@ -690,11 +687,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
}
// Check for non-standard pay-to-script-hash in inputs
- if (fRequireStandard && !AreInputsStandard(tx, m_view)) {
+ const auto& params = args.m_chainparams.GetConsensus();
+ auto taproot_state = VersionBitsState(::ChainActive().Tip(), params, Consensus::DEPLOYMENT_TAPROOT, versionbitscache);
+ if (fRequireStandard && !AreInputsStandard(tx, m_view, taproot_state == ThresholdState::ACTIVE)) {
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
}
- // Check for non-standard witness in P2WSH
+ // Check for non-standard witnesses.
if (tx.HasWitness() && fRequireStandard && !IsWitnessStandard(tx, m_view))
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
@@ -919,7 +918,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
return true;
}
-bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata)
+bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata)
{
const CTransaction& tx = *ws.m_ptx;
@@ -946,7 +945,7 @@ bool MemPoolAccept::PolicyScriptChecks(ATMPArgs& args, Workspace& ws, Precompute
return true;
}
-bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, Workspace& ws, PrecomputedTransactionData& txdata)
+bool MemPoolAccept::ConsensusScriptChecks(ATMPArgs& args, const Workspace& ws, PrecomputedTransactionData& txdata)
{
const CTransaction& tx = *ws.m_ptx;
const uint256& hash = ws.m_hash;
@@ -1310,8 +1309,6 @@ bool CChainState::IsInitialBlockDownload() const
return false;
}
-static CBlockIndex *pindexBestForkTip = nullptr, *pindexBestForkBase = nullptr;
-
static void AlertNotify(const std::string& strMessage)
{
uiInterface.NotifyAlertChanged();
@@ -1337,73 +1334,16 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
AssertLockHeld(cs_main);
// Before we get past initial download, we cannot reliably alert about forks
// (we assume we don't get stuck on a fork before finishing our initial sync)
- if (::ChainstateActive().IsInitialBlockDownload())
+ if (::ChainstateActive().IsInitialBlockDownload()) {
return;
-
- // If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
- // of our head, drop it
- if (pindexBestForkTip && ::ChainActive().Height() - pindexBestForkTip->nHeight >= 72)
- pindexBestForkTip = nullptr;
-
- if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 6)))
- {
- if (!GetfLargeWorkForkFound() && pindexBestForkBase)
- {
- std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
- pindexBestForkBase->phashBlock->ToString() + std::string("'");
- AlertNotify(warning);
- }
- if (pindexBestForkTip && pindexBestForkBase)
- {
- LogPrintf("%s: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n", __func__,
- pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString(),
- pindexBestForkTip->nHeight, pindexBestForkTip->phashBlock->ToString());
- SetfLargeWorkForkFound(true);
- }
- else
- {
- LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__);
- SetfLargeWorkInvalidChainFound(true);
- }
- }
- else
- {
- SetfLargeWorkForkFound(false);
- SetfLargeWorkInvalidChainFound(false);
}
-}
-static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
-{
- AssertLockHeld(cs_main);
- // If we are on a fork that is sufficiently large, set a warning flag
- CBlockIndex* pfork = pindexNewForkTip;
- CBlockIndex* plonger = ::ChainActive().Tip();
- while (pfork && pfork != plonger)
- {
- while (plonger && plonger->nHeight > pfork->nHeight)
- plonger = plonger->pprev;
- if (pfork == plonger)
- break;
- pfork = pfork->pprev;
- }
-
- // We define a condition where we should warn the user about as a fork of at least 7 blocks
- // with a tip within 72 blocks (+/- 12 hours if no one mines it) of ours
- // We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network
- // hash rate operating on the fork.
- // or a chain that is entirely longer than ours and invalid (note that this should be detected by both)
- // We define it this way because it allows us to only store the highest fork tip (+ base) which meets
- // the 7-block condition and from this always have the most-likely-to-cause-warning fork
- if (pfork && (!pindexBestForkTip || pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) &&
- pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) &&
- ::ChainActive().Height() - pindexNewForkTip->nHeight < 72)
- {
- pindexBestForkTip = pindexNewForkTip;
- pindexBestForkBase = pfork;
+ if (pindexBestInvalid && pindexBestInvalid->nChainWork > ::ChainActive().Tip()->nChainWork + (GetBlockProof(*::ChainActive().Tip()) * 6)) {
+ LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__);
+ SetfLargeWorkInvalidChainFound(true);
+ } else {
+ SetfLargeWorkInvalidChainFound(false);
}
-
- CheckForkWarningConditions();
}
// Called both upon regular invalid block discovery *and* InvalidateBlock
@@ -2455,9 +2395,7 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C
}
bilingual_str warning_messages;
- int num_unexpected_version = 0;
- if (!::ChainstateActive().IsInitialBlockDownload())
- {
+ if (!::ChainstateActive().IsInitialBlockDownload()) {
const CBlockIndex* pindex = pindexNew;
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
WarningBitsConditionChecker checker(bit);
@@ -2471,14 +2409,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C
}
}
}
- // Check the version of the last 100 blocks to see if we need to upgrade:
- for (int i = 0; i < 100 && pindex != nullptr; i++)
- {
- int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus());
- if (pindex->nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION && (pindex->nVersion & ~nExpectedVersion) != 0)
- ++num_unexpected_version;
- pindex = pindex->pprev;
- }
}
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)%s\n", __func__,
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
@@ -2486,10 +2416,6 @@ static void UpdateTip(CTxMemPool& mempool, const CBlockIndex* pindexNew, const C
FormatISO8601DateTime(pindexNew->GetBlockTime()),
GuessVerificationProgress(chainParams.TxData(), pindexNew), ::ChainstateActive().CoinsTip().DynamicMemoryUsage() * (1.0 / (1<<20)), ::ChainstateActive().CoinsTip().GetCacheSize(),
!warning_messages.empty() ? strprintf(" warning='%s'", warning_messages.original) : "");
-
- if (num_unexpected_version > 0) {
- LogPrint(BCLog::VALIDATION, "%d of last 100 blocks have unexpected version\n", num_unexpected_version);
- }
}
/** Disconnect m_chain's tip.
@@ -2744,8 +2670,8 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
AssertLockHeld(cs_main);
AssertLockHeld(m_mempool.cs);
- const CBlockIndex *pindexOldTip = m_chain.Tip();
- const CBlockIndex *pindexFork = m_chain.FindFork(pindexMostWork);
+ const CBlockIndex* pindexOldTip = m_chain.Tip();
+ const CBlockIndex* pindexFork = m_chain.FindFork(pindexMostWork);
// Disconnect active blocks which are no longer in the best chain.
bool fBlocksDisconnected = false;
@@ -2765,7 +2691,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
fBlocksDisconnected = true;
}
- // Build list of new blocks to connect.
+ // Build list of new blocks to connect (in descending height order).
std::vector<CBlockIndex*> vpindexToConnect;
bool fContinue = true;
int nHeight = pindexFork ? pindexFork->nHeight : -1;
@@ -2775,7 +2701,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight);
vpindexToConnect.clear();
vpindexToConnect.reserve(nTargetHeight - nHeight);
- CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight);
+ CBlockIndex* pindexIter = pindexMostWork->GetAncestor(nTargetHeight);
while (pindexIter && pindexIter->nHeight != nHeight) {
vpindexToConnect.push_back(pindexIter);
pindexIter = pindexIter->pprev;
@@ -2783,7 +2709,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
nHeight = nTargetHeight;
// Connect new blocks.
- for (CBlockIndex *pindexConnect : reverse_iterate(vpindexToConnect)) {
+ for (CBlockIndex* pindexConnect : reverse_iterate(vpindexToConnect)) {
if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
@@ -2819,11 +2745,7 @@ bool CChainState::ActivateBestChainStep(BlockValidationState& state, const CChai
}
m_mempool.check(&CoinsTip());
- // Callbacks/notifications for a new best chain.
- if (fInvalidFound)
- CheckForkWarningConditionsOnNewFork(vpindexToConnect.back());
- else
- CheckForkWarningConditions();
+ CheckForkWarningConditions();
return true;
}
@@ -5082,7 +5004,7 @@ bool LoadMempool(CTxMemPool& pool)
pool.PrioritiseTransaction(tx->GetHash(), amountdelta);
}
TxValidationState state;
- if (nTime + nExpiryTimeout > nNow) {
+ if (nTime > nNow - nExpiryTimeout) {
LOCK(cs_main);
AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, nTime,
nullptr /* plTxnReplaced */, false /* bypass_limits */,
@@ -5185,7 +5107,9 @@ bool DumpMempool(const CTxMemPool& pool)
if (!FileCommit(file.Get()))
throw std::runtime_error("FileCommit failed");
file.fclose();
- RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "mempool.dat");
+ if (!RenameOver(GetDataDir() / "mempool.dat.new", GetDataDir() / "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) {
diff --git a/src/validation.h b/src/validation.h
index 3d9fa92c15..d10b260d8a 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -42,7 +42,6 @@ class CChainParams;
class CInv;
class CConnman;
class CScriptCheck;
-class CBlockPolicyEstimator;
class CTxMemPool;
class ChainstateManager;
class TxValidationState;
@@ -110,7 +109,6 @@ enum class SynchronizationState {
};
extern RecursiveMutex cs_main;
-extern CBlockPolicyEstimator feeEstimator;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
@@ -503,9 +501,9 @@ enum class CoinsCacheSizeState
* whereas block information and metadata independent of the current tip is
* kept in `BlockMetadataManager`.
*/
-class CChainState {
-private:
-
+class CChainState
+{
+protected:
/**
* Every received block is assigned a unique and increasing identifier, so we
* know which one to give priority in case of a fork.
@@ -564,7 +562,7 @@ public:
//! @returns whether or not the CoinsViews object has been fully initialized and we can
//! safely flush this object to disk.
- bool CanFlushToDisk() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
+ bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
return m_coins_views && m_coins_views->m_cacheview;
}
diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp
index 85aae0170d..6ed48593fb 100644
--- a/src/wallet/bdb.cpp
+++ b/src/wallet/bdb.cpp
@@ -53,16 +53,13 @@ bool WalletDatabaseFileId::operator==(const WalletDatabaseFileId& rhs) const
}
/**
- * @param[in] wallet_path Path to wallet directory. Or (for backwards compatibility only) a path to a berkeley btree data file inside a wallet directory.
- * @param[out] database_filename Filename of berkeley btree data file inside the wallet directory.
+ * @param[in] env_directory Path to environment directory
* @return A shared pointer to the BerkeleyEnvironment object for the wallet directory, never empty because ~BerkeleyEnvironment
* erases the weak pointer from the g_dbenvs map.
* @post A new BerkeleyEnvironment weak pointer is inserted into g_dbenvs if the directory path key was not already in the map.
*/
-std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& wallet_path, std::string& database_filename)
+std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory)
{
- fs::path env_directory;
- SplitWalletPath(wallet_path, env_directory, database_filename);
LOCK(cs_db);
auto inserted = g_dbenvs.emplace(env_directory.string(), std::weak_ptr<BerkeleyEnvironment>());
if (inserted.second) {
@@ -808,21 +805,14 @@ std::unique_ptr<DatabaseBatch> BerkeleyDatabase::MakeBatch(bool flush_on_close)
return MakeUnique<BerkeleyBatch>(*this, false, flush_on_close);
}
-bool ExistsBerkeleyDatabase(const fs::path& path)
-{
- fs::path env_directory;
- std::string data_filename;
- SplitWalletPath(path, env_directory, data_filename);
- return IsBDBFile(env_directory / data_filename);
-}
-
std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
{
+ fs::path data_file = BDBDataFile(path);
std::unique_ptr<BerkeleyDatabase> db;
{
LOCK(cs_db); // Lock env.m_databases until insert in BerkeleyDatabase constructor
- std::string data_filename;
- std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(path, data_filename);
+ std::string data_filename = data_file.filename().string();
+ std::shared_ptr<BerkeleyEnvironment> env = GetBerkeleyEnv(data_file.parent_path());
if (env->m_databases.count(data_filename)) {
error = Untranslated(strprintf("Refusing to load database. Data file '%s' is already loaded.", (env->Directory() / data_filename).string()));
status = DatabaseStatus::FAILED_ALREADY_LOADED;
@@ -839,28 +829,3 @@ std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, con
status = DatabaseStatus::SUCCESS;
return db;
}
-
-bool IsBDBFile(const fs::path& path)
-{
- if (!fs::exists(path)) return false;
-
- // A Berkeley DB Btree file has at least 4K.
- // This check also prevents opening lock files.
- boost::system::error_code ec;
- auto size = fs::file_size(path, ec);
- if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
- if (size < 4096) return false;
-
- fsbridge::ifstream file(path, std::ios::binary);
- if (!file.is_open()) return false;
-
- file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
- uint32_t data = 0;
- file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic
-
- // Berkeley DB Btree magic bytes, from:
- // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
- // - big endian systems - 00 05 31 62
- // - little endian systems - 62 31 05 00
- return data == 0x00053162 || data == 0x62310500;
-}
diff --git a/src/wallet/bdb.h b/src/wallet/bdb.h
index 5403e95ee4..bf1617d67f 100644
--- a/src/wallet/bdb.h
+++ b/src/wallet/bdb.h
@@ -56,7 +56,7 @@ public:
std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
std::condition_variable_any m_db_in_use;
- BerkeleyEnvironment(const fs::path& env_directory);
+ explicit BerkeleyEnvironment(const fs::path& env_directory);
BerkeleyEnvironment();
~BerkeleyEnvironment();
void Reset();
@@ -83,11 +83,8 @@ public:
}
};
-/** Get BerkeleyEnvironment and database filename given a wallet path. */
-std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& wallet_path, std::string& database_filename);
-
-/** Check format of database file */
-bool IsBDBFile(const fs::path& path);
+/** Get BerkeleyEnvironment given a directory path. */
+std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory);
class BerkeleyBatch;
@@ -146,6 +143,7 @@ public:
/** Return path to main database filename */
std::string Filename() override { return (env->Directory() / strFile).string(); }
+ std::string Format() override { return "bdb"; }
/**
* Pointer to shared database environment.
*
@@ -225,9 +223,6 @@ public:
std::string BerkeleyDatabaseVersion();
-//! Check if Berkeley database exists at specified path.
-bool ExistsBerkeleyDatabase(const fs::path& path);
-
//! Return object giving access to Berkeley database at specified path.
std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index bd1d114730..cd49baeb78 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -3,23 +3,130 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <chainparams.h>
#include <fs.h>
+#include <logging.h>
#include <wallet/db.h>
#include <string>
-void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename)
+std::vector<fs::path> ListDatabases(const fs::path& wallet_dir)
+{
+ const size_t offset = wallet_dir.string().size() + 1;
+ std::vector<fs::path> paths;
+ boost::system::error_code ec;
+
+ for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
+ if (ec) {
+ LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string());
+ continue;
+ }
+
+ try {
+ // Get wallet path relative to walletdir by removing walletdir from the wallet path.
+ // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
+ const fs::path path = it->path().string().substr(offset);
+
+ if (it->status().type() == fs::directory_file &&
+ (IsBDBFile(BDBDataFile(it->path())) || IsSQLiteFile(SQLiteDataFile(it->path())))) {
+ // Found a directory which contains wallet.dat btree file, add it as a wallet.
+ paths.emplace_back(path);
+ } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBDBFile(it->path())) {
+ if (it->path().filename() == "wallet.dat") {
+ // Found top-level wallet.dat btree file, add top level directory ""
+ // as a wallet.
+ paths.emplace_back();
+ } else {
+ // Found top-level btree file not called wallet.dat. Current bitcoin
+ // software will never create these files but will allow them to be
+ // opened in a shared database environment for backwards compatibility.
+ // Add it to the list of available wallets.
+ paths.emplace_back(path);
+ }
+ }
+ } catch (const std::exception& e) {
+ LogPrintf("%s: Error scanning %s: %s\n", __func__, it->path().string(), e.what());
+ it.no_push();
+ }
+ }
+
+ return paths;
+}
+
+fs::path BDBDataFile(const fs::path& wallet_path)
{
if (fs::is_regular_file(wallet_path)) {
// Special case for backwards compatibility: if wallet path points to an
// existing file, treat it as the path to a BDB data file in a parent
// directory that also contains BDB log files.
- env_directory = wallet_path.parent_path();
- database_filename = wallet_path.filename().string();
+ return wallet_path;
} else {
// Normal case: Interpret wallet path as a directory path containing
// data and log files.
- env_directory = wallet_path;
- database_filename = "wallet.dat";
+ return wallet_path / "wallet.dat";
}
}
+
+fs::path SQLiteDataFile(const fs::path& path)
+{
+ return path / "wallet.dat";
+}
+
+bool IsBDBFile(const fs::path& path)
+{
+ if (!fs::exists(path)) return false;
+
+ // A Berkeley DB Btree file has at least 4K.
+ // This check also prevents opening lock files.
+ boost::system::error_code ec;
+ auto size = fs::file_size(path, ec);
+ if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
+ if (size < 4096) return false;
+
+ fsbridge::ifstream file(path, std::ios::binary);
+ if (!file.is_open()) return false;
+
+ file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
+ uint32_t data = 0;
+ file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic
+
+ // Berkeley DB Btree magic bytes, from:
+ // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
+ // - big endian systems - 00 05 31 62
+ // - little endian systems - 62 31 05 00
+ return data == 0x00053162 || data == 0x62310500;
+}
+
+bool IsSQLiteFile(const fs::path& path)
+{
+ if (!fs::exists(path)) return false;
+
+ // A SQLite Database file is at least 512 bytes.
+ boost::system::error_code ec;
+ auto size = fs::file_size(path, ec);
+ if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
+ if (size < 512) return false;
+
+ fsbridge::ifstream file(path, std::ios::binary);
+ if (!file.is_open()) return false;
+
+ // Magic is at beginning and is 16 bytes long
+ char magic[16];
+ file.read(magic, 16);
+
+ // Application id is at offset 68 and 4 bytes long
+ file.seekg(68, std::ios::beg);
+ char app_id[4];
+ file.read(app_id, 4);
+
+ file.close();
+
+ // Check the magic, see https://sqlite.org/fileformat2.html
+ std::string magic_str(magic, 16);
+ if (magic_str != std::string("SQLite format 3", 16)) {
+ return false;
+ }
+
+ // Check the application id matches our network magic
+ return memcmp(Params().MessageStart(), app_id, 4) == 0;
+}
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 3ecccd4e00..2c75486a44 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -144,6 +144,8 @@ public:
/** Return path to main database file for logs and error messages. */
virtual std::string Filename() = 0;
+ virtual std::string Format() = 0;
+
std::atomic<unsigned int> nUpdateCounter;
unsigned int nLastSeen;
unsigned int nLastFlushed;
@@ -190,6 +192,7 @@ public:
void IncrementUpdateCounter() override { ++nUpdateCounter; }
void ReloadDbEnv() override {}
std::string Filename() override { return "dummy"; }
+ std::string Format() override { return "dummy"; }
std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override { return MakeUnique<DummyBatch>(); }
};
@@ -220,6 +223,14 @@ enum class DatabaseStatus {
FAILED_ENCRYPT,
};
+/** Recursively list database paths in directory. */
+std::vector<fs::path> ListDatabases(const fs::path& path);
+
std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
+fs::path BDBDataFile(const fs::path& path);
+fs::path SQLiteDataFile(const fs::path& path);
+bool IsBDBFile(const fs::path& path);
+bool IsSQLiteFile(const fs::path& path);
+
#endif // BITCOIN_WALLET_DB_H
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 6cbad14de8..1bbfa197d7 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -111,7 +111,7 @@ static feebumper::Result CheckFeeRate(const CWallet& wallet, const CWalletTx& wt
return feebumper::Result::OK;
}
-static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CAmount old_fee, CCoinControl& coin_control)
+static CFeeRate EstimateFeeRate(const CWallet& wallet, const CWalletTx& wtx, const CAmount old_fee, const CCoinControl& coin_control)
{
// Get the fee rate of the original transaction. This is calculated from
// the tx fee/vsize, so it may have been rounded down. Add 1 satoshi to the
@@ -215,7 +215,7 @@ Result CreateRateBumpTransaction(CWallet& wallet, const uint256& txid, const CCo
// We cannot source new unconfirmed inputs(bip125 rule 2)
new_coin_control.m_min_depth = 1;
- CTransactionRef tx_new = MakeTransactionRef();
+ CTransactionRef tx_new;
CAmount fee_ret;
int change_pos_in_out = -1; // No requested location for change
bilingual_str fail_reason;
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 5d8c4fba29..085dde1026 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -15,6 +15,9 @@
#include <util/moneystr.h>
#include <util/system.h>
#include <util/translation.h>
+#ifdef USE_BDB
+#include <wallet/bdb.h>
+#endif
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
#include <walletinitinterface.h>
@@ -60,7 +63,7 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
argsman.AddArg("-rescan", "Rescan the block chain for missing wallet transactions on startup", ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
- argsman.AddArg("-wallet=<path>", "Specify wallet database path. Can be specified multiple times to load multiple wallets. Path is interpreted relative to <walletdir> if it is not absolute, and will be created if it does not exist (as a directory containing a wallet.dat file and log files). For backwards compatibility this will also accept names of existing data files in <walletdir>.)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
+ argsman.AddArg("-wallet=<path>", "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>.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
argsman.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
argsman.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::WALLET);
#if HAVE_SYSTEM
@@ -68,9 +71,14 @@ void WalletInit::AddWalletOptions(ArgsManager& argsman) const
#endif
argsman.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::WALLET);
+#ifdef USE_BDB
argsman.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
argsman.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
argsman.AddArg("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
+#else
+ argsman.AddHiddenArgs({"-dblogsize", "-flushwallet", "-privdb"});
+#endif
+
argsman.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::WALLET_DEBUG_TEST);
argsman.AddHiddenArgs({"-zapwallettxes"});
diff --git a/src/interfaces/wallet.cpp b/src/wallet/interfaces.cpp
index f68016b557..e4e8c50f4f 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/wallet/interfaces.cpp
@@ -31,9 +31,22 @@
#include <utility>
#include <vector>
-namespace interfaces {
-namespace {
+using interfaces::Chain;
+using interfaces::FoundBlock;
+using interfaces::Handler;
+using interfaces::MakeHandler;
+using interfaces::Wallet;
+using interfaces::WalletAddress;
+using interfaces::WalletBalances;
+using interfaces::WalletClient;
+using interfaces::WalletOrderForm;
+using interfaces::WalletTx;
+using interfaces::WalletTxOut;
+using interfaces::WalletTxStatus;
+using interfaces::WalletValueMap;
+namespace wallet {
+namespace {
//! Construct wallet tx struct.
WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
{
@@ -64,7 +77,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
}
//! Construct wallet tx status struct.
-WalletTxStatus MakeWalletTxStatus(CWallet& wallet, const CWalletTx& wtx)
+WalletTxStatus MakeWalletTxStatus(const CWallet& wallet, const CWalletTx& wtx)
{
WalletTxStatus result;
result.block_height = wtx.m_confirm.block_height > 0 ? wtx.m_confirm.block_height : std::numeric_limits<int>::max();
@@ -81,7 +94,7 @@ WalletTxStatus MakeWalletTxStatus(CWallet& wallet, const CWalletTx& wtx)
}
//! Construct wallet TxOut struct.
-WalletTxOut MakeWalletTxOut(CWallet& wallet,
+WalletTxOut MakeWalletTxOut(const CWallet& wallet,
const CWalletTx& wtx,
int n,
int depth) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
@@ -538,7 +551,7 @@ public:
std::vector<std::string> listWalletDir() override
{
std::vector<std::string> paths;
- for (auto& path : ListWalletDir()) {
+ for (auto& path : ListDatabases(GetWalletDir())) {
paths.push_back(path.string());
}
return paths;
@@ -561,14 +574,14 @@ public:
std::vector<std::unique_ptr<Handler>> m_rpc_handlers;
std::list<CRPCCommand> m_rpc_commands;
};
-
} // namespace
+} // namespace wallet
-std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<WalletImpl>(wallet) : nullptr; }
+namespace interfaces {
+std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return wallet ? MakeUnique<wallet::WalletImpl>(wallet) : nullptr; }
std::unique_ptr<WalletClient> MakeWalletClient(Chain& chain, ArgsManager& args)
{
- return MakeUnique<WalletClientImpl>(chain, args);
+ return MakeUnique<wallet::WalletClientImpl>(chain, args);
}
-
} // namespace interfaces
diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp
index 1b057000d2..036fd4956f 100644
--- a/src/wallet/load.cpp
+++ b/src/wallet/load.cpp
@@ -65,17 +65,22 @@ bool VerifyWallets(interfaces::Chain& chain)
const fs::path path = fs::absolute(wallet_file, GetWalletDir());
if (!wallet_paths.insert(path).second) {
- chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
- return false;
+ chain.initWarning(strprintf(_("Ignoring duplicate -wallet %s."), wallet_file));
+ continue;
}
DatabaseOptions options;
DatabaseStatus status;
+ options.require_existing = true;
options.verify = true;
bilingual_str error_string;
if (!MakeWalletDatabase(wallet_file, options, status, error_string)) {
- chain.initError(error_string);
- return false;
+ if (status == DatabaseStatus::FAILED_NOT_FOUND) {
+ chain.initWarning(Untranslated(strprintf("Skipping -wallet path that doesn't exist. %s\n", error_string.original)));
+ } else {
+ chain.initError(error_string);
+ return false;
+ }
}
}
@@ -85,13 +90,21 @@ bool VerifyWallets(interfaces::Chain& chain)
bool LoadWallets(interfaces::Chain& chain)
{
try {
+ std::set<fs::path> wallet_paths;
for (const std::string& name : gArgs.GetArgs("-wallet")) {
+ if (!wallet_paths.insert(name).second) {
+ continue;
+ }
DatabaseOptions options;
DatabaseStatus status;
+ options.require_existing = true;
options.verify = false; // No need to verify, assuming verified earlier in VerifyWallets()
bilingual_str error;
std::vector<bilingual_str> warnings;
std::unique_ptr<WalletDatabase> database = MakeWalletDatabase(name, options, status, error);
+ if (!database && status == DatabaseStatus::FAILED_NOT_FOUND) {
+ continue;
+ }
std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(chain, name, std::move(database), options.create_flags, error, warnings) : nullptr;
if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n")));
if (!pwallet) {
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 7dcab46ad3..6b46868d10 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -340,8 +340,9 @@ RPCHelpMan importprunedfunds()
CWallet* const pwallet = wallet.get();
CMutableTransaction tx;
- if (!DecodeHexTx(tx, request.params[0].get_str()))
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ if (!DecodeHexTx(tx, request.params[0].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
+ }
uint256 hashTx = tx.GetHash();
CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
@@ -1522,7 +1523,9 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue&
// Need to ExpandPrivate to check if private keys are available for all pubkeys
FlatSigningProvider expand_keys;
std::vector<CScript> scripts;
- parsed_desc->Expand(0, keys, scripts, expand_keys);
+ if (!parsed_desc->Expand(0, keys, scripts, expand_keys)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot expand descriptor. Probably because of hardened derivations without private keys provided");
+ }
parsed_desc->ExpandPrivate(0, keys, expand_keys);
// Check if all private keys are provided
@@ -1558,7 +1561,7 @@ static UniValue ProcessDescriptorImport(CWallet * const pwallet, const UniValue&
}
// Add descriptor to the wallet
- auto spk_manager = pwallet->AddWalletDescriptor(w_desc, keys, label);
+ auto spk_manager = pwallet->AddWalletDescriptor(w_desc, keys, label, internal);
if (spk_manager == nullptr) {
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Could not add descriptor '%s'", descriptor));
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 23291e3a48..94a73b67df 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -8,6 +8,7 @@
#include <interfaces/chain.h>
#include <key_io.h>
#include <node/context.h>
+#include <optional.h>
#include <outputtype.h>
#include <policy/feerate.h>
#include <policy/fees.h>
@@ -47,8 +48,6 @@ using interfaces::FoundBlock;
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
static const std::string HELP_REQUIRING_PASSPHRASE{"\nRequires wallet passphrase to be set with walletpassphrase call if wallet is encrypted.\n"};
-static const uint32_t WALLET_BTC_KB_TO_SAT_B = COIN / 1000; // 1 sat / B = 0.00001 BTC / kB
-
static inline bool GetAvoidReuseFlag(const CWallet* const pwallet, const UniValue& param) {
bool can_avoid_reuse = pwallet->IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
bool avoid_reuse = param.isNull() ? can_avoid_reuse : param.get_bool();
@@ -198,36 +197,36 @@ static std::string LabelFromValue(const UniValue& value)
/**
* Update coin control with fee estimation based on the given parameters
*
- * @param[in] pwallet Wallet pointer
- * @param[in,out] cc Coin control which is to be updated
- * @param[in] estimate_mode String value (e.g. "ECONOMICAL")
- * @param[in] estimate_param Parameter (blocks to confirm, explicit fee rate, etc)
- * @throws a JSONRPCError if estimate_mode is unknown, or if estimate_param is missing when required
+ * @param[in] wallet Wallet reference
+ * @param[in,out] cc Coin control to be updated
+ * @param[in] conf_target UniValue integer; confirmation target in blocks, values between 1 and 1008 are valid per policy/fees.h;
+ * @param[in] estimate_mode UniValue string; fee estimation mode, valid values are "unset", "economical" or "conservative";
+ * @param[in] fee_rate UniValue real; fee rate in sat/vB;
+ * if present, both conf_target and estimate_mode must either be null, or "unset"
+ * @param[in] override_min_fee bool; whether to set fOverrideFeeRate to true to disable minimum fee rate checks and instead
+ * verify only that fee_rate is greater than 0
+ * @throws a JSONRPCError if conf_target, estimate_mode, or fee_rate contain invalid values or are in conflict
*/
-static void SetFeeEstimateMode(const CWallet* pwallet, CCoinControl& cc, const UniValue& estimate_mode, const UniValue& estimate_param)
+static void SetFeeEstimateMode(const CWallet& wallet, CCoinControl& cc, const UniValue& conf_target, const UniValue& estimate_mode, const UniValue& fee_rate, bool override_min_fee)
{
- if (!estimate_mode.isNull()) {
- if (!FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid estimate_mode parameter");
- }
- }
-
- if (cc.m_fee_mode == FeeEstimateMode::BTC_KB || cc.m_fee_mode == FeeEstimateMode::SAT_B) {
- if (estimate_param.isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Selected estimate_mode requires a fee rate");
+ if (!fee_rate.isNull()) {
+ if (!conf_target.isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
}
-
- CAmount fee_rate = AmountFromValue(estimate_param);
- if (cc.m_fee_mode == FeeEstimateMode::SAT_B) {
- fee_rate /= WALLET_BTC_KB_TO_SAT_B;
+ if (!estimate_mode.isNull() && estimate_mode.get_str() != "unset") {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and fee_rate");
}
-
- cc.m_feerate = CFeeRate(fee_rate);
-
- // default RBF to true for explicit fee rate modes
+ cc.m_feerate = CFeeRate(AmountFromValue(fee_rate), COIN);
+ if (override_min_fee) cc.fOverrideFeeRate = true;
+ // Default RBF to true for explicit fee_rate, if unset.
if (cc.m_signal_bip125_rbf == nullopt) cc.m_signal_bip125_rbf = true;
- } else if (!estimate_param.isNull()) {
- cc.m_confirm_target = ParseConfirmTarget(estimate_param, pwallet->chain().estimateMaxBlocks());
+ return;
+ }
+ if (!estimate_mode.isNull() && !FeeModeFromString(estimate_mode.get_str(), cc.m_fee_mode)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, InvalidEstimateModeErrorMessage());
+ }
+ if (!conf_target.isNull()) {
+ cc.m_confirm_target = ParseConfirmTarget(conf_target, wallet.chain().estimateMaxBlocks());
}
}
@@ -440,11 +439,12 @@ static RPCHelpMan sendtoaddress()
{"subtractfeefromamount", RPCArg::Type::BOOL, /* 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, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
- {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
" \"" + FeeModes("\"\n\"") + "\""},
{"avoid_reuse", RPCArg::Type::BOOL, /* 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."},
+ {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"verbose", RPCArg::Type::BOOL, /* default */ "false", "If true, return extra information about the transaction."},
},
{
@@ -460,12 +460,17 @@ static RPCHelpMan sendtoaddress()
},
},
RPCExamples{
- HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1")
- + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"seans outpost\"")
- + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" true")
- + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 0.00002 " + (CURRENCY_UNIT + "/kB"))
- + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" false true 2 " + (CURRENCY_ATOM + "/B"))
- + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"")
+ "\nSend 0.1 BTC\n"
+ + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") +
+ "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode using positional arguments\n"
+ + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"sean's outpost\" false true 6 economical") +
+ "\nSend 0.1 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB, subtract fee from amount, BIP125-replaceable, using positional arguments\n"
+ + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"drinks\" \"room77\" true true null \"unset\" null 1.1") +
+ "\nSend 0.2 BTC with a confirmation target of 6 blocks in economical fee estimate mode using named arguments\n"
+ + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.2 conf_target=6 estimate_mode=\"economical\"") +
+ "\nSend 0.5 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n"
+ + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25")
+ + HelpExampleCli("-named sendtoaddress", "address=\"" + EXAMPLE_ADDRESS[0] + "\" amount=0.5 fee_rate=25 subtractfeefromamount=false replaceable=true avoid_reuse=true comment=\"2 pizzas\" comment_to=\"jeremy\" verbose=true")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
@@ -500,7 +505,7 @@ static RPCHelpMan sendtoaddress()
// We also enable partial spend avoidance if reuse avoidance is set.
coin_control.m_avoid_partial_spends |= coin_control.m_avoid_address_reuse;
- SetFeeEstimateMode(pwallet, coin_control, request.params[7], request.params[6]);
+ SetFeeEstimateMode(*pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[9], /* override_min_fee */ false);
EnsureWalletIsUnlocked(pwallet);
@@ -514,7 +519,7 @@ static RPCHelpMan sendtoaddress()
std::vector<CRecipient> recipients;
ParseRecipients(address_amounts, subtractFeeFromAmount, recipients);
- bool verbose = request.params[9].isNull() ? false: request.params[9].get_bool();
+ const bool verbose{request.params[10].isNull() ? false : request.params[10].get_bool()};
return SendMoney(pwallet, coin_control, recipients, mapValue, verbose);
},
@@ -868,9 +873,10 @@ static RPCHelpMan sendmany()
},
},
{"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Allow this transaction to be replaced by a transaction with higher fees via BIP 125"},
- {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
" \"" + FeeModes("\"\n\"") + "\""},
+ {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"verbose", RPCArg::Type::BOOL, /* default */ "false", "If true, return extra infomration about the transaction."},
},
{
@@ -927,11 +933,11 @@ static RPCHelpMan sendmany()
coin_control.m_signal_bip125_rbf = request.params[5].get_bool();
}
- SetFeeEstimateMode(pwallet, coin_control, request.params[7], request.params[6]);
+ SetFeeEstimateMode(*pwallet, coin_control, /* conf_target */ request.params[6], /* estimate_mode */ request.params[7], /* fee_rate */ request.params[8], /* override_min_fee */ false);
std::vector<CRecipient> recipients;
ParseRecipients(sendTo, subtractFeeFromAmount, recipients);
- bool verbose = request.params[8].isNull() ? false : request.params[8].get_bool();
+ const bool verbose{request.params[9].isNull() ? false : request.params[9].get_bool()};
return SendMoney(pwallet, coin_control, recipients, std::move(mapValue), verbose);
},
@@ -2308,7 +2314,7 @@ static RPCHelpMan settxfee()
"\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n"
"Can be deactivated by passing 0 as the fee. In that case automatic fee selection will be used by default.\n",
{
- {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kB"},
+ {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The transaction fee in " + CURRENCY_UNIT + "/kvB"},
},
RPCResult{
RPCResult::Type::BOOL, "", "Returns true if successful"
@@ -2422,6 +2428,7 @@ static RPCHelpMan getwalletinfo()
{
{RPCResult::Type::STR, "walletname", "the wallet name"},
{RPCResult::Type::NUM, "walletversion", "the wallet version"},
+ {RPCResult::Type::STR, "format", "the database format (bdb or sqlite)"},
{RPCResult::Type::STR_AMOUNT, "balance", "DEPRECATED. Identical to getbalances().mine.trusted"},
{RPCResult::Type::STR_AMOUNT, "unconfirmed_balance", "DEPRECATED. Identical to getbalances().mine.untrusted_pending"},
{RPCResult::Type::STR_AMOUNT, "immature_balance", "DEPRECATED. Identical to getbalances().mine.immature"},
@@ -2430,7 +2437,7 @@ static RPCHelpMan getwalletinfo()
{RPCResult::Type::NUM, "keypoolsize", "how many new keys are pre-generated (only counts external keys)"},
{RPCResult::Type::NUM, "keypoolsize_hd_internal", "how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)"},
{RPCResult::Type::NUM_TIME, "unlocked_until", /* optional */ true, "the " + UNIX_EPOCH_TIME + " until which the wallet is unlocked for transfers, or 0 if the wallet is locked (only present for passphrase-encrypted wallets)"},
- {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB"},
+ {RPCResult::Type::STR_AMOUNT, "paytxfee", "the transaction fee configuration, set in " + CURRENCY_UNIT + "/kvB"},
{RPCResult::Type::STR_HEX, "hdseedid", /* optional */ true, "the Hash160 of the HD seed (only present when HD is enabled)"},
{RPCResult::Type::BOOL, "private_keys_enabled", "false if privatekeys are disabled for this wallet (enforced watch-only wallet)"},
{RPCResult::Type::BOOL, "avoid_reuse", "whether this wallet tracks clean/dirty coins in terms of reuse"},
@@ -2465,6 +2472,7 @@ static RPCHelpMan getwalletinfo()
int64_t kp_oldest = pwallet->GetOldestKeyPoolTime();
obj.pushKV("walletname", pwallet->GetName());
obj.pushKV("walletversion", pwallet->GetVersion());
+ obj.pushKV("format", pwallet->GetDatabase().Format());
obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
@@ -2529,7 +2537,7 @@ static RPCHelpMan listwalletdir()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
UniValue wallets(UniValue::VARR);
- for (const auto& path : ListWalletDir()) {
+ for (const auto& path : ListDatabases(GetWalletDir())) {
UniValue wallet(UniValue::VOBJ);
wallet.pushKV("name", path.string());
wallets.push_back(wallet);
@@ -2740,10 +2748,19 @@ static RPCHelpMan createwallet()
flags |= WALLET_FLAG_AVOID_REUSE;
}
if (!request.params[5].isNull() && request.params[5].get_bool()) {
+#ifndef USE_SQLITE
+ throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without sqlite support (required for descriptor wallets)");
+#endif
flags |= WALLET_FLAG_DESCRIPTORS;
warnings.emplace_back(Untranslated("Wallet is an experimental descriptor wallet"));
}
+#ifndef USE_BDB
+ if (!(flags & WALLET_FLAG_DESCRIPTORS)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Compiled without bdb support (required for legacy wallets)");
+ }
+#endif
+
DatabaseOptions options;
DatabaseStatus status;
options.require_create = true;
@@ -2772,7 +2789,7 @@ static RPCHelpMan unloadwallet()
"Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n"
"Specifying the wallet name on a wallet endpoint is invalid.",
{
- {"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC request", "The name of the wallet to unload."},
+ {"wallet_name", RPCArg::Type::STR, /* default */ "the wallet name from the RPC endpoint", "The name of the wallet to unload. If provided both here and in the RPC endpoint, the two must be identical."},
{"load_on_startup", RPCArg::Type::BOOL, /* default */ "null", "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."},
},
RPCResult{RPCResult::Type::OBJ, "", "", {
@@ -2786,8 +2803,8 @@ static RPCHelpMan unloadwallet()
{
std::string wallet_name;
if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) {
- if (!request.params[0].isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot unload the requested wallet");
+ if (!(request.params[0].isNull() || request.params[0].get_str() == wallet_name)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "RPC endpoint wallet and wallet_name parameter specify different wallets");
}
} else {
wallet_name = request.params[0].get_str();
@@ -3039,7 +3056,7 @@ static RPCHelpMan listunspent()
};
}
-void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, UniValue options, CCoinControl& coinControl)
+void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& fee_out, int& change_position, const UniValue& options, CCoinControl& coinControl, bool override_min_fee)
{
// 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
@@ -3072,7 +3089,8 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
{"lockUnspents", UniValueType(UniValue::VBOOL)},
{"lock_unspents", UniValueType(UniValue::VBOOL)},
{"locktime", UniValueType(UniValue::VNUM)},
- {"feeRate", UniValueType()}, // will be checked below
+ {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode()
+ {"feeRate", UniValueType()}, // will be checked by AmountFromValue() below
{"psbt", UniValueType(UniValue::VBOOL)},
{"subtractFeeFromOutputs", UniValueType(UniValue::VARR)},
{"subtract_fee_from_outputs", UniValueType(UniValue::VARR)},
@@ -3119,10 +3137,12 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
lockUnspents = (options.exists("lock_unspents") ? options["lock_unspents"] : options["lockUnspents"]).get_bool();
}
- if (options.exists("feeRate"))
- {
+ if (options.exists("feeRate")) {
+ if (options.exists("fee_rate")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both fee_rate (" + CURRENCY_ATOM + "/vB) and feeRate (" + CURRENCY_UNIT + "/kvB)");
+ }
if (options.exists("conf_target")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate");
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both conf_target and feeRate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
}
if (options.exists("estimate_mode")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot specify both estimate_mode and feeRate");
@@ -3137,7 +3157,7 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
if (options.exists("replaceable")) {
coinControl.m_signal_bip125_rbf = options["replaceable"].get_bool();
}
- SetFeeEstimateMode(pwallet, coinControl, options["estimate_mode"], options["conf_target"]);
+ SetFeeEstimateMode(*pwallet, coinControl, options["conf_target"], options["estimate_mode"], options["fee_rate"], override_min_fee);
}
} else {
// if options is null and not a bool
@@ -3194,7 +3214,8 @@ static RPCHelpMan fundrawtransaction()
"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."},
{"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
- {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"},
+ {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
+ {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."},
{"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The integers.\n"
"The fee will be equally deducted from the amount of each specified output.\n"
"Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
@@ -3205,7 +3226,7 @@ static RPCHelpMan fundrawtransaction()
},
{"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n"
"Allows this transaction to be replaced by a transaction with higher fees"},
- {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
" \"" + FeeModes("\"\n\"") + "\""},
},
@@ -3257,7 +3278,7 @@ static RPCHelpMan fundrawtransaction()
CCoinControl coin_control;
// Automatically select (additional) coins. Can be overridden by options.add_inputs.
coin_control.m_add_inputs = true;
- FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control);
+ FundTransaction(pwallet, tx, fee, change_position, request.params[1], coin_control, /* override_min_fee */ true);
UniValue result(UniValue::VOBJ);
result.pushKV("hex", EncodeHexTx(CTransaction(tx)));
@@ -3331,8 +3352,8 @@ RPCHelpMan signrawtransactionwithwallet()
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true);
CMutableTransaction mtx;
- if (!DecodeHexTx(mtx, request.params[0].get_str(), true)) {
- throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ if (!DecodeHexTx(mtx, request.params[0].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
}
// Sign the transaction
@@ -3365,34 +3386,38 @@ RPCHelpMan signrawtransactionwithwallet()
static RPCHelpMan bumpfee_helper(std::string method_name)
{
bool want_psbt = method_name == "psbtbumpfee";
+ const std::string incremental_fee{CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE).ToString(FeeEstimateMode::SAT_VB)};
return RPCHelpMan{method_name,
"\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n"
+ std::string(want_psbt ? "Returns a PSBT instead of creating and signing a new transaction.\n" : "") +
"An opt-in RBF transaction with the given txid must be in the wallet.\n"
- "The command will 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.\n"
+ "The command will pay the additional fee by reducing change outputs or adding inputs when necessary.\n"
+ "It may add a new change output if one does not already exist.\n"
"All inputs in the original transaction will be included in the replacement transaction.\n"
"The command will fail if the wallet or mempool contains a transaction that spends one of T's outputs.\n"
- "By default, the new fee will be calculated automatically using estimatesmartfee.\n"
+ "By default, the new fee will be calculated automatically using the estimatesmartfee RPC.\n"
"The user can specify a confirmation target for estimatesmartfee.\n"
- "Alternatively, the user can specify a fee_rate (" + CURRENCY_UNIT + " per kB) for the new transaction.\n"
+ "Alternatively, the user can specify a fee rate in " + CURRENCY_ATOM + "/vB for the new transaction.\n"
"At a minimum, the new fee rate must be high enough to pay an additional new relay fee (incrementalfee\n"
- "returned by getnetworkinfo) to enter the node's mempool.\n",
+ "returned by getnetworkinfo) to enter the node's mempool.\n"
+ "* WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB. *\n",
{
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The txid to be bumped"},
{"options", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED_NAMED_ARG, "",
{
- {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks)"},
- {"fee_rate", RPCArg::Type::NUM, /* default */ "fall back to 'conf_target'", "fee rate (NOT total fee) to pay, in " + CURRENCY_UNIT + " per kB\n"
- "Specify a fee rate instead of relying on the built-in fee estimator.\n"
- "Must be at least 0.0001 " + CURRENCY_UNIT + " per kB higher than the current transaction fee rate.\n"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks\n"},
+ {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation",
+ "\nSpecify a fee rate in " + CURRENCY_ATOM + "/vB instead of relying on the built-in fee estimator.\n"
+ "Must be at least " + incremental_fee + " higher than the current transaction fee rate.\n"
+ "WARNING: before version 0.21, fee_rate was in " + CURRENCY_UNIT + "/kvB. As of 0.21, fee_rate is in " + CURRENCY_ATOM + "/vB.\n"},
{"replaceable", RPCArg::Type::BOOL, /* default */ "true", "Whether the new transaction should still be\n"
"marked bip-125 replaceable. If true, the sequence numbers in the transaction will\n"
"be left unchanged from the original. If false, any input sequence numbers in the\n"
"original transaction that were less than 0xfffffffe will be increased to 0xfffffffe\n"
"so the new transaction will not be explicitly bip-125 replaceable (though it may\n"
"still be replaceable in practice, for example if it has unconfirmed ancestors which\n"
- "are replaceable)."},
+ "are replaceable).\n"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
" \"" + FeeModes("\"\n\"") + "\""},
},
@@ -3445,7 +3470,7 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
{
{"confTarget", UniValueType(UniValue::VNUM)},
{"conf_target", UniValueType(UniValue::VNUM)},
- {"fee_rate", UniValueType(UniValue::VNUM)},
+ {"fee_rate", UniValueType()}, // will be checked by AmountFromValue() in SetFeeEstimateMode()
{"replaceable", UniValueType(UniValue::VBOOL)},
{"estimate_mode", UniValueType(UniValue::VSTR)},
},
@@ -3457,23 +3482,10 @@ static RPCHelpMan bumpfee_helper(std::string method_name)
auto conf_target = options.exists("confTarget") ? options["confTarget"] : options["conf_target"];
- if (!conf_target.isNull()) {
- if (options.exists("fee_rate")) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.");
- }
- coin_control.m_confirm_target = ParseConfirmTarget(conf_target, pwallet->chain().estimateMaxBlocks());
- } else if (options.exists("fee_rate")) {
- CFeeRate fee_rate(AmountFromValue(options["fee_rate"]));
- if (fee_rate <= CFeeRate(0)) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid fee_rate %s (must be greater than 0)", fee_rate.ToString()));
- }
- coin_control.m_feerate = fee_rate;
- }
-
if (options.exists("replaceable")) {
coin_control.m_signal_bip125_rbf = options["replaceable"].get_bool();
}
- SetFeeEstimateMode(pwallet, coin_control, options["estimate_mode"], conf_target);
+ SetFeeEstimateMode(*pwallet, coin_control, conf_target, options["estimate_mode"], options["fee_rate"], /* override_min_fee */ false);
}
// Make sure the results are valid at least up to the most recent block
@@ -3585,7 +3597,7 @@ static RPCHelpMan rescanblockchain()
}
int start_height = 0;
- Optional<int> stop_height;
+ Optional<int> stop_height = MakeOptional(false, int());
uint256 start_block;
{
LOCK(pwallet->cs_wallet);
@@ -4009,9 +4021,10 @@ static RPCHelpMan send()
},
},
},
- {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
" \"" + FeeModes("\"\n\"") + "\""},
+ {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "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, "",
{
{"add_inputs", RPCArg::Type::BOOL, /* default */ "false", "If inputs are specified, automatically include more if they are not enough."},
@@ -4019,9 +4032,10 @@ static RPCHelpMan send()
{"change_address", RPCArg::Type::STR_HEX, /* default */ "pool address", "The bitcoin address to receive the change"},
{"change_position", RPCArg::Type::NUM, /* default */ "random", "The index of the change output"},
{"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if change_address is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
- {"conf_target", RPCArg::Type::NUM, /* default */ "wallet default", "Confirmation target (in blocks), or fee rate (for " + CURRENCY_UNIT + "/kB or " + CURRENCY_ATOM + "/B estimate modes)"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
" \"" + FeeModes("\"\n\"") + "\""},
+ {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
{"include_watching", RPCArg::Type::BOOL, /* default */ "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."},
@@ -4035,7 +4049,7 @@ static RPCHelpMan send()
{"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
{"lock_unspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
{"psbt", RPCArg::Type::BOOL, /* default */ "automatic", "Always return a PSBT, implies add_to_wallet=false."},
- {"subtract_fee_from_outputs", RPCArg::Type::ARR, /* default */ "empty array", "A JSON array of integers.\n"
+ {"subtract_fee_from_outputs", RPCArg::Type::ARR, /* default */ "empty array", "Outputs to subtract the fee from, specified as integer indices.\n"
"The fee will be equally deducted from the amount of each specified output.\n"
"Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
"If no outputs are specified here, the sender pays the fee.",
@@ -4058,18 +4072,25 @@ static RPCHelpMan send()
}
},
RPCExamples{""
- "\nSend with a fee rate of 1 satoshi per byte\n"
- + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 sat/b\n") +
- "\nCreate a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n"
+ "\nSend 0.1 BTC with a confirmation target of 6 blocks in economical fee estimate mode\n"
+ + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 6 economical\n") +
+ "Send 0.2 BTC with a fee rate of 1.1 " + CURRENCY_ATOM + "/vB using positional arguments\n"
+ + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" 1.1\n") +
+ "Send 0.2 BTC with a fee rate of 1 " + CURRENCY_ATOM + "/vB using the options argument\n"
+ + HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.2}' null \"unset\" null '{\"fee_rate\": 1}'\n") +
+ "Send 0.3 BTC with a fee rate of 25 " + CURRENCY_ATOM + "/vB using named arguments\n"
+ + HelpExampleCli("-named send", "outputs='{\"" + EXAMPLE_ADDRESS[0] + "\": 0.3}' fee_rate=25\n") +
+ "Create a transaction that should confirm the next block, with a specific input, and return result without adding to wallet or broadcasting to the network\n"
+ HelpExampleCli("send", "'{\"" + EXAMPLE_ADDRESS[0] + "\": 0.1}' 1 economical '{\"add_to_wallet\": false, \"inputs\": [{\"txid\":\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\", \"vout\":1}]}'")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
RPCTypeCheck(request.params, {
- UniValueType(), // ARR or OBJ, checked later
- UniValue::VNUM,
- UniValue::VSTR,
- UniValue::VOBJ
+ UniValueType(), // outputs (ARR or OBJ, checked later)
+ UniValue::VNUM, // conf_target
+ UniValue::VSTR, // estimate_mode
+ UniValueType(), // fee_rate, will be checked by AmountFromValue() in SetFeeEstimateMode()
+ UniValue::VOBJ, // options
}, true
);
@@ -4077,18 +4098,28 @@ static RPCHelpMan send()
if (!wallet) return NullUniValue;
CWallet* const pwallet = wallet.get();
- UniValue options = request.params[3];
- if (options.exists("feeRate") || options.exists("fee_rate") || options.exists("estimate_mode") || options.exists("conf_target")) {
+ UniValue options{request.params[4].isNull() ? UniValue::VOBJ : request.params[4]};
+ if (options.exists("conf_target") || options.exists("estimate_mode")) {
if (!request.params[1].isNull() || !request.params[2].isNull()) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Use either conf_target and estimate_mode or the options dictionary to control fee rate");
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass conf_target and estimate_mode either as arguments or in the options object, but not both");
}
} else {
options.pushKV("conf_target", request.params[1]);
options.pushKV("estimate_mode", request.params[2]);
}
+ if (options.exists("fee_rate")) {
+ if (!request.params[3].isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Pass the fee_rate either as an argument, or in the options object, but not both");
+ }
+ } else {
+ options.pushKV("fee_rate", request.params[3]);
+ }
if (!options["conf_target"].isNull() && (options["estimate_mode"].isNull() || (options["estimate_mode"].get_str() == "unset"))) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Specify estimate_mode");
}
+ if (options.exists("feeRate")) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Use fee_rate (" + CURRENCY_ATOM + "/vB) instead of feeRate");
+ }
if (options.exists("changeAddress")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Use change_address");
}
@@ -4116,9 +4147,9 @@ static RPCHelpMan send()
CMutableTransaction rawTx = ConstructTransaction(options["inputs"], request.params[0], options["locktime"], rbf);
CCoinControl coin_control;
// Automatically select coins, unless at least one is manually selected. Can
- // be overriden by options.add_inputs.
+ // be overridden by options.add_inputs.
coin_control.m_add_inputs = rawTx.vin.size() == 0;
- FundTransaction(pwallet, rawTx, fee, change_position, options, coin_control);
+ FundTransaction(pwallet, rawTx, fee, change_position, options, coin_control, /* override_min_fee */ false);
bool add_to_wallet = true;
if (options.exists("add_to_wallet")) {
@@ -4203,7 +4234,7 @@ static RPCHelpMan sethdseed()
// Do not do anything to non-HD wallets
if (!pwallet->CanSupportFeature(FEATURE_HD)) {
- throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set a HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
+ throw JSONRPCError(RPC_WALLET_ERROR, "Cannot set an HD seed on a non-HD wallet. Use the upgradewallet RPC in order to upgrade a non-HD wallet to HD");
}
EnsureWalletIsUnlocked(pwallet);
@@ -4346,7 +4377,8 @@ static RPCHelpMan walletcreatefundedpsbt()
{"change_type", RPCArg::Type::STR, /* default */ "set by -changetype", "The output type to use. Only valid if changeAddress is not specified. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
{"includeWatching", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Also select inputs which are watch only"},
{"lockUnspents", RPCArg::Type::BOOL, /* default */ "false", "Lock selected unspent outputs"},
- {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set: makes wallet determine the fee", "Set a specific fee rate in " + CURRENCY_UNIT + "/kB"},
+ {"fee_rate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_ATOM + "/vB."},
+ {"feeRate", RPCArg::Type::AMOUNT, /* default */ "not set, fall back to wallet fee estimation", "Specify a fee rate in " + CURRENCY_UNIT + "/kvB."},
{"subtractFeeFromOutputs", RPCArg::Type::ARR, /* default */ "empty array", "The outputs to subtract the fee from.\n"
"The fee will be equally deducted from the amount of each specified output.\n"
"Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
@@ -4357,7 +4389,7 @@ static RPCHelpMan walletcreatefundedpsbt()
},
{"replaceable", RPCArg::Type::BOOL, /* default */ "wallet default", "Marks this transaction as BIP125 replaceable.\n"
"Allows this transaction to be replaced by a transaction with higher fees"},
- {"conf_target", RPCArg::Type::NUM, /* default */ "fall back to wallet's confirmation target (txconfirmtarget)", "Confirmation target (in blocks)"},
+ {"conf_target", RPCArg::Type::NUM, /* default */ "wallet -txconfirmtarget", "Confirmation target in blocks"},
{"estimate_mode", RPCArg::Type::STR, /* default */ "unset", std::string() + "The fee estimate mode, must be one of (case insensitive):\n"
" \"" + FeeModes("\"\n\"") + "\""},
},
@@ -4404,7 +4436,7 @@ static RPCHelpMan walletcreatefundedpsbt()
// Automatically select coins, unless at least one is manually selected. Can
// be overridden by options.add_inputs.
coin_control.m_add_inputs = rawTx.vin.size() == 0;
- FundTransaction(pwallet, rawTx, fee, change_position, request.params[3], coin_control);
+ FundTransaction(pwallet, rawTx, fee, change_position, request.params[3], coin_control, /* override_min_fee */ true);
// Make a blank psbt
PartiallySignedTransaction psbtx(rawTx);
@@ -4433,12 +4465,21 @@ static RPCHelpMan walletcreatefundedpsbt()
static RPCHelpMan upgradewallet()
{
return RPCHelpMan{"upgradewallet",
- "\nUpgrade the wallet. Upgrades to the latest version if no version number is specified\n"
+ "\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, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version"}
+ {"version", RPCArg::Type::NUM, /* default */ strprintf("%d", FEATURE_LATEST), "The version number to upgrade to. Default is the latest wallet version."}
+ },
+ RPCResult{
+ RPCResult::Type::OBJ, "", "",
+ {
+ {RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
+ {RPCResult::Type::NUM, "previous_version", "Version of wallet before this operation"},
+ {RPCResult::Type::NUM, "current_version", "Version of wallet after this operation"},
+ {RPCResult::Type::STR, "result", /* optional */ true, "Description of result, if no error"},
+ {RPCResult::Type::STR, "error", /* optional */ true, "Error message (if there is one)"}
+ },
},
- RPCResults{},
RPCExamples{
HelpExampleCli("upgradewallet", "169900")
+ HelpExampleRpc("upgradewallet", "169900")
@@ -4457,13 +4498,31 @@ static RPCHelpMan upgradewallet()
if (!request.params[0].isNull()) {
version = request.params[0].get_int();
}
-
bilingual_str error;
- std::vector<bilingual_str> warnings;
- if (!pwallet->UpgradeWallet(version, error, warnings)) {
- throw JSONRPCError(RPC_WALLET_ERROR, error.original);
+ const int previous_version{pwallet->GetVersion()};
+ const bool wallet_upgraded{pwallet->UpgradeWallet(version, error)};
+ const int current_version{pwallet->GetVersion()};
+ std::string result;
+
+ if (wallet_upgraded) {
+ if (previous_version == current_version) {
+ result = "Already at latest version. Wallet version unchanged.";
+ } else {
+ result = strprintf("Wallet upgraded successfully from version %i to version %i.", previous_version, current_version);
+ }
}
- return error.original;
+
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("wallet_name", pwallet->GetName());
+ obj.pushKV("previous_version", previous_version);
+ obj.pushKV("current_version", current_version);
+ if (!result.empty()) {
+ obj.pushKV("result", result);
+ } else {
+ CHECK_NONFATAL(!error.empty());
+ obj.pushKV("error", error.original);
+ }
+ return obj;
},
};
}
@@ -4530,9 +4589,9 @@ static const CRPCCommand commands[] =
{ "wallet", "lockunspent", &lockunspent, {"unlock","transactions"} },
{ "wallet", "removeprunedfunds", &removeprunedfunds, {"txid"} },
{ "wallet", "rescanblockchain", &rescanblockchain, {"start_height", "stop_height"} },
- { "wallet", "send", &send, {"outputs","conf_target","estimate_mode","options"} },
- { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode","verbose"} },
- { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse","verbose"} },
+ { "wallet", "send", &send, {"outputs","conf_target","estimate_mode","fee_rate","options"} },
+ { "wallet", "sendmany", &sendmany, {"dummy","amounts","minconf","comment","subtractfeefrom","replaceable","conf_target","estimate_mode","fee_rate","verbose"} },
+ { "wallet", "sendtoaddress", &sendtoaddress, {"address","amount","comment","comment_to","subtractfeefromamount","replaceable","conf_target","estimate_mode","avoid_reuse","fee_rate","verbose"} },
{ "wallet", "sethdseed", &sethdseed, {"newkeypool","seed"} },
{ "wallet", "setlabel", &setlabel, {"address","label"} },
{ "wallet", "settxfee", &settxfee, {"amount"} },
diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp
index 225b975067..09a9ec68cd 100644
--- a/src/wallet/salvage.cpp
+++ b/src/wallet/salvage.cpp
@@ -6,6 +6,7 @@
#include <fs.h>
#include <streams.h>
#include <util/translation.h>
+#include <wallet/bdb.h>
#include <wallet/salvage.h>
#include <wallet/wallet.h>
#include <wallet/walletdb.h>
@@ -27,11 +28,13 @@ bool RecoverDatabaseFile(const fs::path& file_path, bilingual_str& error, std::v
DatabaseStatus status;
options.require_existing = true;
options.verify = false;
+ options.require_format = DatabaseFormat::BERKELEY;
std::unique_ptr<WalletDatabase> database = MakeDatabase(file_path, options, status, error);
if (!database) return false;
- std::string filename;
- std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, filename);
+ BerkeleyDatabase& berkeley_database = static_cast<BerkeleyDatabase&>(*database);
+ std::string filename = berkeley_database.Filename();
+ std::shared_ptr<BerkeleyEnvironment> env = berkeley_database.env;
if (!env->Open(error)) {
return false;
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index b7c70dac3a..15972fe7bb 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -3,12 +3,15 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <key_io.h>
+#include <logging.h>
#include <outputtype.h>
#include <script/descriptor.h>
#include <script/sign.h>
#include <util/bip32.h>
#include <util/strencodings.h>
#include <util/string.h>
+#include <util/system.h>
+#include <util/time.h>
#include <util/translation.h>
#include <wallet/scriptpubkeyman.h>
@@ -438,12 +441,12 @@ bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal) const
return keypool_has_keys;
}
-bool LegacyScriptPubKeyMan::Upgrade(int prev_version, bilingual_str& error)
+bool LegacyScriptPubKeyMan::Upgrade(int prev_version, int new_version, bilingual_str& error)
{
LOCK(cs_KeyStore);
bool hd_upgrade = false;
bool split_upgrade = false;
- if (m_storage.CanSupportFeature(FEATURE_HD) && !IsHDEnabled()) {
+ if (IsFeatureSupported(new_version, FEATURE_HD) && !IsHDEnabled()) {
WalletLogPrintf("Upgrading wallet to HD\n");
m_storage.SetMinVersion(FEATURE_HD);
@@ -453,10 +456,17 @@ bool LegacyScriptPubKeyMan::Upgrade(int prev_version, bilingual_str& error)
hd_upgrade = true;
}
// Upgrade to HD chain split if necessary
- if (m_storage.CanSupportFeature(FEATURE_HD_SPLIT) && CHDChain::VERSION_HD_CHAIN_SPLIT) {
+ if (!IsFeatureSupported(prev_version, FEATURE_HD_SPLIT) && IsFeatureSupported(new_version, FEATURE_HD_SPLIT)) {
WalletLogPrintf("Upgrading wallet to use HD chain split\n");
m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
split_upgrade = FEATURE_HD_SPLIT > prev_version;
+ // Upgrade the HDChain
+ if (m_hd_chain.nVersion < CHDChain::VERSION_HD_CHAIN_SPLIT) {
+ m_hd_chain.nVersion = CHDChain::VERSION_HD_CHAIN_SPLIT;
+ if (!WalletBatch(m_storage.GetDatabase()).WriteHDChain(m_hd_chain)) {
+ throw std::runtime_error(std::string(__func__) + ": writing chain failed");
+ }
+ }
}
// Mark all keys currently in the keypool as pre-split
if (split_upgrade) {
diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h
index 14fb1fa89f..cec46a0fbb 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/time.h>
#include <wallet/crypter.h>
#include <wallet/ismine.h>
#include <wallet/walletdb.h>
@@ -33,11 +34,11 @@ class WalletStorage
public:
virtual ~WalletStorage() = default;
virtual const std::string GetDisplayName() const = 0;
- virtual WalletDatabase& GetDatabase() = 0;
+ virtual WalletDatabase& GetDatabase() const = 0;
virtual bool IsWalletFlagSet(uint64_t) const = 0;
virtual void UnsetBlankWalletFlag(WalletBatch&) = 0;
virtual bool CanSupportFeature(enum WalletFeature) const = 0;
- virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr, bool = false) = 0;
+ virtual void SetMinVersion(enum WalletFeature, WalletBatch* = nullptr) = 0;
virtual const CKeyingMaterial& GetEncryptionKey() const = 0;
virtual bool HasEncryptionKeys() const = 0;
virtual bool IsLocked() const = 0;
@@ -171,7 +172,7 @@ protected:
WalletStorage& m_storage;
public:
- ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
+ explicit ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
virtual ~ScriptPubKeyMan() {};
virtual bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) { return false; }
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
@@ -206,7 +207,7 @@ public:
virtual bool CanGetAddresses(bool internal = false) const { return false; }
/** Upgrades the wallet to the specified version */
- virtual bool Upgrade(int prev_version, bilingual_str& error) { return false; }
+ virtual bool Upgrade(int prev_version, int new_version, bilingual_str& error) { return false; }
virtual bool HavePrivateKeys() const { return false; }
@@ -371,7 +372,7 @@ public:
bool SetupGeneration(bool force = false) override;
- bool Upgrade(int prev_version, bilingual_str& error) override;
+ bool Upgrade(int prev_version, int new_version, bilingual_str& error) override;
bool HavePrivateKeys() const override;
@@ -503,7 +504,7 @@ class LegacySigningProvider : public SigningProvider
private:
const LegacyScriptPubKeyMan& m_spk_man;
public:
- LegacySigningProvider(const LegacyScriptPubKeyMan& spk_man) : m_spk_man(spk_man) {}
+ explicit LegacySigningProvider(const LegacyScriptPubKeyMan& spk_man) : m_spk_man(spk_man) {}
bool GetCScript(const CScriptID &scriptid, CScript& script) const override { return m_spk_man.GetCScript(scriptid, script); }
bool HaveCScript(const CScriptID &scriptid) const override { return m_spk_man.HaveCScript(scriptid); }
diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp
index 02a161ecbd..0fb3b1d3c4 100644
--- a/src/wallet/sqlite.cpp
+++ b/src/wallet/sqlite.cpp
@@ -17,7 +17,6 @@
#include <sqlite3.h>
#include <stdint.h>
-static const char* const DATABASE_FILENAME = "wallet.dat";
static constexpr int32_t WALLET_SCHEMA_VERSION = 0;
static Mutex g_sqlite_mutex;
@@ -206,7 +205,9 @@ void SQLiteDatabase::Open()
}
if (m_db == nullptr) {
- TryCreateDirectories(m_dir_path);
+ if (!m_mock) {
+ TryCreateDirectories(m_dir_path);
+ }
int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr);
if (ret != SQLITE_OK) {
throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret)));
@@ -566,25 +567,20 @@ bool SQLiteBatch::TxnAbort()
return res == SQLITE_OK;
}
-bool ExistsSQLiteDatabase(const fs::path& path)
-{
- const fs::path file = path / DATABASE_FILENAME;
- return fs::symlink_status(file).type() == fs::regular_file && IsSQLiteFile(file);
-}
-
std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
{
- const fs::path file = path / DATABASE_FILENAME;
try {
- auto db = MakeUnique<SQLiteDatabase>(path, file);
+ fs::path data_file = SQLiteDataFile(path);
+ auto db = MakeUnique<SQLiteDatabase>(data_file.parent_path(), data_file);
if (options.verify && !db->Verify(error)) {
status = DatabaseStatus::FAILED_VERIFY;
return nullptr;
}
+ status = DatabaseStatus::SUCCESS;
return db;
} catch (const std::runtime_error& e) {
status = DatabaseStatus::FAILED_LOAD;
- error.original = e.what();
+ error = Untranslated(e.what());
return nullptr;
}
}
@@ -593,37 +589,3 @@ std::string SQLiteDatabaseVersion()
{
return std::string(sqlite3_libversion());
}
-
-bool IsSQLiteFile(const fs::path& path)
-{
- if (!fs::exists(path)) return false;
-
- // A SQLite Database file is at least 512 bytes.
- boost::system::error_code ec;
- auto size = fs::file_size(path, ec);
- if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
- if (size < 512) return false;
-
- fsbridge::ifstream file(path, std::ios::binary);
- if (!file.is_open()) return false;
-
- // Magic is at beginning and is 16 bytes long
- char magic[16];
- file.read(magic, 16);
-
- // Application id is at offset 68 and 4 bytes long
- file.seekg(68, std::ios::beg);
- char app_id[4];
- file.read(app_id, 4);
-
- file.close();
-
- // Check the magic, see https://sqlite.org/fileformat2.html
- std::string magic_str(magic);
- if (magic_str != std::string("SQLite format 3")) {
- return false;
- }
-
- // Check the application id matches our network magic
- return memcmp(Params().MessageStart(), app_id, 4) == 0;
-}
diff --git a/src/wallet/sqlite.h b/src/wallet/sqlite.h
index 5e5e93903b..442563184e 100644
--- a/src/wallet/sqlite.h
+++ b/src/wallet/sqlite.h
@@ -105,6 +105,7 @@ public:
void IncrementUpdateCounter() override { ++nUpdateCounter; }
std::string Filename() override { return m_file_path; }
+ std::string Format() override { return "sqlite"; }
/** Make a SQLiteBatch connected to this database */
std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
@@ -112,10 +113,8 @@ public:
sqlite3* m_db{nullptr};
};
-bool ExistsSQLiteDatabase(const fs::path& path);
std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
std::string SQLiteDatabaseVersion();
-bool IsSQLiteFile(const fs::path& path);
#endif // BITCOIN_WALLET_SQLITE_H
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index f38ccba384..019161415c 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -64,7 +64,8 @@ static void add_coin(CWallet& wallet, const CAmount& nValue, int nAge = 6*24, bo
if (spendable) {
CTxDestination dest;
std::string error;
- assert(wallet.GetNewDestination(OutputType::BECH32, "", dest, error));
+ const bool destination_ok = wallet.GetNewDestination(OutputType::BECH32, "", dest, error);
+ assert(destination_ok);
tx.vout[nInput].scriptPubKey = GetScriptForDestination(dest);
}
if (fIsFromMe) {
@@ -283,7 +284,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// Make sure that can use BnB when there are preset inputs
empty_wallet();
{
- std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
+ std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->SetupLegacyScriptPubKeyMan();
diff --git a/src/wallet/test/db_tests.cpp b/src/wallet/test/db_tests.cpp
index 8f0083cd2e..1a28852a6b 100644
--- a/src/wallet/test/db_tests.cpp
+++ b/src/wallet/test/db_tests.cpp
@@ -13,6 +13,13 @@
BOOST_FIXTURE_TEST_SUITE(db_tests, BasicTestingSetup)
+static std::shared_ptr<BerkeleyEnvironment> GetWalletEnv(const fs::path& path, std::string& database_filename)
+{
+ fs::path data_file = BDBDataFile(path);
+ database_filename = data_file.filename().string();
+ return GetBerkeleyEnv(data_file.parent_path());
+}
+
BOOST_AUTO_TEST_CASE(getwalletenv_file)
{
std::string test_name = "test_name.dat";
diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
index c80310045a..334e4ae0d8 100644
--- a/src/wallet/test/init_test_fixture.cpp
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -10,7 +10,7 @@
InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
- m_wallet_client = MakeWalletClient(*m_chain, *Assert(m_node.args));
+ m_wallet_client = MakeWalletClient(*m_node.chain, *Assert(m_node.args));
std::string sep;
sep += fs::path::preferred_separator;
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
index f5bade77df..f666c45a34 100644
--- a/src/wallet/test/init_test_fixture.h
+++ b/src/wallet/test/init_test_fixture.h
@@ -19,7 +19,6 @@ struct InitWalletDirTestingSetup: public BasicTestingSetup {
fs::path m_datadir;
fs::path m_cwd;
std::map<std::string, fs::path> m_walletdir_path_cases;
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<interfaces::WalletClient> m_wallet_client;
};
diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp
index d5aed99d99..0ef8b9c4bf 100644
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -27,8 +27,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
CKey uncompressedKey;
uncompressedKey.MakeNewKey(false);
CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
+ std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
CScript scriptPubKey;
isminetype result;
diff --git a/src/wallet/test/scriptpubkeyman_tests.cpp b/src/wallet/test/scriptpubkeyman_tests.cpp
index f7c1337b0d..347a436429 100644
--- a/src/wallet/test/scriptpubkeyman_tests.cpp
+++ b/src/wallet/test/scriptpubkeyman_tests.cpp
@@ -17,9 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(scriptpubkeyman_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(CanProvide)
{
// Set up wallet and keyman variables.
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
LegacyScriptPubKeyMan& keyman = *wallet.GetOrCreateLegacyScriptPubKeyMan();
// Make a 1 of 2 multisig script
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index 4d6f427618..badf2eb459 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -6,10 +6,10 @@
WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
: TestingSetup(chainName),
- m_wallet(m_chain.get(), "", CreateMockWalletDatabase())
+ m_wallet(m_node.chain.get(), "", CreateMockWalletDatabase())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
- m_chain_notifications_handler = m_chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
+ m_chain_notifications_handler = m_node.chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
m_wallet_client->registerRpcs();
}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index ba8a5ff1f3..ab7fb8c42b 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -20,8 +20,7 @@
struct WalletTestingSetup : public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
- std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_chain, *Assert(m_node.args));
+ std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_node.chain, *Assert(m_node.args));
CWallet m_wallet;
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
};
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index c42114c394..a6db261914 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -28,6 +28,8 @@ RPCHelpMan importmulti();
RPCHelpMan dumpwallet();
RPCHelpMan importwallet();
+extern RecursiveMutex cs_wallets;
+
// Ensure that fee levels defined in the wallet are at least as high
// as the default levels for node policy.
static_assert(DEFAULT_TRANSACTION_MINFEE >= DEFAULT_MIN_RELAY_TX_FEE, "wallet minimum fee is smaller than default relay fee");
@@ -83,12 +85,9 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
// Verify ScanForWalletTransactions fails to read an unknown start block.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -107,7 +106,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -133,7 +132,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions only picks transactions in the new block
// file.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -158,7 +157,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions scans no blocks.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -183,9 +182,6 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
// Prune the older block file.
{
LOCK(cs_main);
@@ -197,7 +193,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
// before the missing block, and success for a key whose creation time is
// after.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
WITH_LOCK(wallet->cs_wallet, wallet->SetLastBlockProcessed(newTip->nHeight, newTip->GetBlockHash()));
AddWallet(wallet);
@@ -255,14 +251,11 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
std::string backup_file = (GetDataDir() / "wallet.backup").string();
// Import key into wallet and call dumpwallet to create backup file.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
@@ -284,7 +277,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
LOCK(wallet->cs_wallet);
wallet->SetupLegacyScriptPubKeyMan();
@@ -317,10 +310,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// debit functions.
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
CWalletTx wtx(&wallet, m_coinbase_txns.back());
@@ -495,7 +485,7 @@ public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- wallet = MakeUnique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
+ wallet = MakeUnique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
{
LOCK2(wallet->cs_wallet, ::cs_main);
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -545,7 +535,6 @@ public:
return it->second;
}
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<CWallet> wallet;
};
@@ -612,9 +601,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
@@ -688,7 +675,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
BOOST_CHECK_EXCEPTION(vr >> w_desc, std::ios_base::failure, malformed_descriptor);
}
-//! Test CreateWalletFromFile function and its behavior handling potential race
+//! Test CWallet::Create() and its behavior handling potential race
//! conditions if it's called the same time an incoming transaction shows up in
//! the mempool or a new block.
//!
@@ -706,11 +693,10 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
//! wallet rescan and notifications are immediately synced, to verify the wallet
//! must already have a handler in place for them, and there's no gap after
//! rescanning where new transactions in new blocks could be lost.
-BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, TestChain100Setup)
+BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
{
// Create new wallet with known key and unload it.
- auto chain = interfaces::MakeChain(m_node);
- auto wallet = TestLoadWallet(*chain);
+ auto wallet = TestLoadWallet(*m_node.chain);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);
@@ -745,12 +731,12 @@ BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, TestChain100Setup)
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
- BOOST_CHECK(chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
// Reload wallet and make sure new transactions are detected despite events
// being blocked
- wallet = TestLoadWallet(*chain);
+ wallet = TestLoadWallet(*m_node.chain);
BOOST_CHECK(rescan_completed);
BOOST_CHECK_EQUAL(addtx_count, 2);
{
@@ -777,18 +763,20 @@ BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, TestChain100Setup)
// deadlock during the sync and simulates a new block notification happening
// as soon as possible.
addtx_count = 0;
- auto handler = HandleLoadWallet([&](std::unique_ptr<interfaces::Wallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->wallet()->cs_wallet) {
+ auto handler = HandleLoadWallet([&](std::unique_ptr<interfaces::Wallet> wallet) EXCLUSIVE_LOCKS_REQUIRED(wallet->wallet()->cs_wallet, cs_wallets) {
BOOST_CHECK(rescan_completed);
m_coinbase_txns.push_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
- BOOST_CHECK(chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ LEAVE_CRITICAL_SECTION(cs_wallets);
LEAVE_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
SyncWithValidationInterfaceQueue();
ENTER_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
+ ENTER_CRITICAL_SECTION(cs_wallets);
});
- wallet = TestLoadWallet(*chain);
+ wallet = TestLoadWallet(*m_node.chain);
BOOST_CHECK_EQUAL(addtx_count, 4);
{
LOCK(wallet->cs_wallet);
@@ -802,8 +790,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{
- auto chain = interfaces::MakeChain(m_node);
- auto wallet = TestLoadWallet(*chain);
+ auto wallet = TestLoadWallet(*m_node.chain);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);
diff --git a/src/wallet/test/walletdb_tests.cpp b/src/wallet/test/walletdb_tests.cpp
new file mode 100644
index 0000000000..a3859e2e4b
--- /dev/null
+++ b/src/wallet/test/walletdb_tests.cpp
@@ -0,0 +1,29 @@
+// Copyright (c) 2012-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 <test/util/setup_common.h>
+#include <clientversion.h>
+#include <streams.h>
+#include <uint256.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(walletdb_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(walletdb_readkeyvalue)
+{
+ /**
+ * When ReadKeyValue() reads from either a "key" or "wkey" it first reads the CDataStream steam into a
+ * CPrivKey or CWalletKey respectively and then reads a hash of the pubkey and privkey into a uint256.
+ * Wallets from 0.8 or before do not store the pubkey/privkey hash, trying to read the hash from old
+ * wallets throws an exception, for backwards compatibility this read is wrapped in a try block to
+ * silently fail. The test here makes sure the type of exception thrown from CDataStream::read()
+ * matches the type we expect, otherwise we need to update the "key"/"wkey" exception type caught.
+ */
+ CDataStream ssValue(SER_DISK, CLIENT_VERSION);
+ uint256 dummy;
+ BOOST_CHECK_THROW(ssValue >> dummy, std::ios_base::failure);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 6b7d05fdf3..3e37491a23 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -52,7 +52,7 @@ const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS{
static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10;
-static RecursiveMutex cs_wallets;
+RecursiveMutex cs_wallets;
static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets);
@@ -100,6 +100,7 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
if (i != vpwallets.end()) return false;
vpwallets.push_back(wallet);
wallet->ConnectScriptPubKeyManNotifiers();
+ wallet->NotifyCanGetAddressesChanged();
return true;
}
@@ -418,7 +419,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
return false;
if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
return false;
- WalletBatch(*database).WriteMasterKey(pMasterKey.first, pMasterKey.second);
+ WalletBatch(GetDatabase()).WriteMasterKey(pMasterKey.first, pMasterKey.second);
if (fWasLocked)
Lock();
return true;
@@ -431,27 +432,19 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
void CWallet::chainStateFlushed(const CBlockLocator& loc)
{
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
batch.WriteBestBlock(loc);
}
-void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in, bool fExplicit)
+void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in)
{
LOCK(cs_wallet);
if (nWalletVersion >= nVersion)
return;
-
- // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
- if (fExplicit && nVersion > nWalletMaxVersion)
- nVersion = FEATURE_LATEST;
-
nWalletVersion = nVersion;
- if (nVersion > nWalletMaxVersion)
- nWalletMaxVersion = nVersion;
-
{
- WalletBatch* batch = batch_in ? batch_in : new WalletBatch(*database);
+ WalletBatch* batch = batch_in ? batch_in : new WalletBatch(GetDatabase());
if (nWalletVersion > 40000)
batch->WriteMinVersion(nWalletVersion);
if (!batch_in)
@@ -459,18 +452,6 @@ void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch* batch_in,
}
}
-bool CWallet::SetMaxVersion(int nVersion)
-{
- LOCK(cs_wallet);
- // cannot downgrade below current version
- if (nWalletVersion > nVersion)
- return false;
-
- nWalletMaxVersion = nVersion;
-
- return true;
-}
-
std::set<uint256> CWallet::GetConflicts(const uint256& txid) const
{
std::set<uint256> result;
@@ -503,12 +484,12 @@ bool CWallet::HasWalletSpend(const uint256& txid) const
void CWallet::Flush()
{
- database->Flush();
+ GetDatabase().Flush();
}
void CWallet::Close()
{
- database->Close();
+ GetDatabase().Close();
}
void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> range)
@@ -634,7 +615,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
{
LOCK(cs_wallet);
mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
- WalletBatch* encrypted_batch = new WalletBatch(*database);
+ WalletBatch* encrypted_batch = new WalletBatch(GetDatabase());
if (!encrypted_batch->TxnBegin()) {
delete encrypted_batch;
encrypted_batch = nullptr;
@@ -655,7 +636,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
}
// Encryption was introduced in version 0.4.0
- SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch, true);
+ SetMinVersion(FEATURE_WALLETCRYPT, encrypted_batch);
if (!encrypted_batch->TxnCommit()) {
delete encrypted_batch;
@@ -686,12 +667,12 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
// Need to completely rewrite the wallet file; if we don't, bdb might keep
// bits of the unencrypted private key in slack space in the database file.
- database->Rewrite();
+ GetDatabase().Rewrite();
// BDB seems to have a bad habit of writing old data into
// slack space in .dat files; that is bad if the old data is
// unencrypted private keys. So:
- database->ReloadDbEnv();
+ GetDatabase().ReloadDbEnv();
}
NotifyStatusChanged(this);
@@ -702,7 +683,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
DBErrors CWallet::ReorderTransactions()
{
LOCK(cs_wallet);
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
// Old wallets didn't have any defined order for transactions
// Probably a bad idea to change the output of this
@@ -763,7 +744,7 @@ int64_t CWallet::IncOrderPosNext(WalletBatch* batch)
if (batch) {
batch->WriteOrderPosNext(nOrderPosNext);
} else {
- WalletBatch(*database).WriteOrderPosNext(nOrderPosNext);
+ WalletBatch(GetDatabase()).WriteOrderPosNext(nOrderPosNext);
}
return nRet;
}
@@ -793,7 +774,7 @@ bool CWallet::MarkReplaced(const uint256& originalHash, const uint256& newHash)
wtx.mapValue["replaced_by_txid"] = newHash.ToString();
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
bool success = true;
if (!batch.WriteTx(wtx)) {
@@ -865,7 +846,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmatio
{
LOCK(cs_wallet);
- WalletBatch batch(*database, fFlushOnClose);
+ WalletBatch batch(GetDatabase(), fFlushOnClose);
uint256 hash = tx->GetHash();
@@ -965,11 +946,12 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx
}
// If wallet doesn't have a chain (e.g wallet-tool), don't bother to update txn.
if (HaveChain()) {
- Optional<int> block_height = chain().getBlockHeight(wtx.m_confirm.hashBlock);
- if (block_height) {
+ bool active;
+ int height;
+ if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
// Update cached block height variable since it not stored in the
// serialized transaction.
- wtx.m_confirm.block_height = *block_height;
+ wtx.m_confirm.block_height = height;
} else if (wtx.isConflicted() || wtx.isConfirmed()) {
// If tx block (or conflicting block) was reorged out of chain
// while the wallet was shutdown, change tx status to UNCONFIRMED
@@ -1064,7 +1046,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
{
LOCK(cs_wallet);
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
std::set<uint256> todo;
std::set<uint256> done;
@@ -1127,7 +1109,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
return;
// Do not flush the wallet here for performance reasons
- WalletBatch batch(*database, false);
+ WalletBatch batch(GetDatabase(), false);
std::set<uint256> todo;
std::set<uint256> done;
@@ -1465,13 +1447,13 @@ void CWallet::SetWalletFlag(uint64_t flags)
{
LOCK(cs_wallet);
m_wallet_flags |= flags;
- if (!WalletBatch(*database).WriteWalletFlags(m_wallet_flags))
+ if (!WalletBatch(GetDatabase()).WriteWalletFlags(m_wallet_flags))
throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
}
void CWallet::UnsetWalletFlag(uint64_t flag)
{
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
UnsetWalletFlagWithDB(batch, flag);
}
@@ -1510,7 +1492,7 @@ bool CWallet::AddWalletFlags(uint64_t flags)
LOCK(cs_wallet);
// We should never be writing unknown non-tolerable wallet flags
assert(((flags & KNOWN_WALLET_FLAGS) >> 32) == (flags >> 32));
- if (!WalletBatch(*database).WriteWalletFlags(flags)) {
+ if (!WalletBatch(GetDatabase()).WriteWalletFlags(flags)) {
throw std::runtime_error(std::string(__func__) + ": writing wallet flags failed");
}
@@ -1601,7 +1583,7 @@ bool CWallet::ImportScriptPubKeys(const std::string& label, const std::set<CScri
return false;
}
if (apply_label) {
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
for (const CScript& script : script_pub_keys) {
CTxDestination dest;
ExtractDestination(script, dest);
@@ -1777,7 +1759,11 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
double progress_current = progress_begin;
int block_height = start_height;
while (!fAbortRescan && !chain().shutdownRequested()) {
- m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
+ if (progress_end - progress_begin > 0.0) {
+ m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
+ } else { // avoid divide-by-zero for single block scan range (i.e. start and stop hashes are equal)
+ m_scanning_progress = 0;
+ }
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))));
}
@@ -1786,18 +1772,22 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
}
+ // Read block data
CBlock block;
- bool next_block;
+ chain().findBlock(block_hash, FoundBlock().data(block));
+
+ // Find next block separately from reading data above, because reading
+ // is slow and there might be a reorg while it is read.
+ bool block_still_active = false;
+ bool next_block = false;
uint256 next_block_hash;
- bool reorg = false;
- if (chain().findBlock(block_hash, FoundBlock().data(block)) && !block.IsNull()) {
+ chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
+
+ if (!block.IsNull()) {
LOCK(cs_wallet);
- next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
- if (reorg) {
+ if (!block_still_active) {
// Abort scan if current block is no longer active, to prevent
// marking transactions as coming from the wrong block.
- // TODO: This should return success instead of failure, see
- // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518
result.last_failed_block = block_hash;
result.status = ScanResult::FAILURE;
break;
@@ -1812,13 +1802,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
// could not scan block, keep scanning but record this block as the most recent failure
result.last_failed_block = block_hash;
result.status = ScanResult::FAILURE;
- next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
}
if (max_height && block_height >= *max_height) {
break;
}
{
- if (!next_block || reorg) {
+ if (!next_block) {
// break successfully when rescan has reached the tip, or
// previous block is no longer on the chain due to a reorg
break;
@@ -2833,7 +2822,7 @@ bool CWallet::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 && nFeeRateNeeded > *coin_control.m_feerate) {
- error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(), nFeeRateNeeded.ToString());
+ error = strprintf(_("Fee rate (%s) is lower than the minimum fee rate setting (%s)"), coin_control.m_feerate->ToString(FeeEstimateMode::SAT_VB), nFeeRateNeeded.ToString(FeeEstimateMode::SAT_VB));
return false;
}
@@ -3105,10 +3094,10 @@ bool CWallet::CreateTransactionInternal(
WalletLogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d 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, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay,
feeCalc.est.pass.start, feeCalc.est.pass.end,
- 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool),
+ (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) > 0.0 ? 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool) : 0.0,
feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool,
feeCalc.est.fail.start, feeCalc.est.fail.end,
- 100 * feeCalc.est.fail.withinTarget / (feeCalc.est.fail.totalConfirmed + feeCalc.est.fail.inMempool + feeCalc.est.fail.leftMempool),
+ (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 true;
}
@@ -3124,13 +3113,14 @@ bool CWallet::CreateTransaction(
bool sign)
{
int nChangePosIn = nChangePosInOut;
- CTransactionRef tx2 = tx;
+ Assert(!tx); // tx is an out-param. TODO change the return type from bool to tx (or nullptr)
bool res = CreateTransactionInternal(vecSend, tx, nFeeRet, nChangePosInOut, error, coin_control, fee_calc_out, sign);
// try with avoidpartialspends unless it's enabled already
if (res && nFeeRet > 0 /* 0 means non-functional fee rate estimation */ && m_max_aps_fee > -1 && !coin_control.m_avoid_partial_spends) {
CCoinControl tmp_cc = coin_control;
tmp_cc.m_avoid_partial_spends = true;
CAmount nFeeRet2;
+ CTransactionRef tx2;
int nChangePosInOut2 = nChangePosIn;
bilingual_str error2; // fired and forgotten; if an error occurs, we discard the results
if (CreateTransactionInternal(vecSend, tx2, nFeeRet2, nChangePosInOut2, error2, tmp_cc, fee_calc_out, sign)) {
@@ -3192,10 +3182,10 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
LOCK(cs_wallet);
fFirstRunRet = false;
- DBErrors nLoadWalletRet = WalletBatch(*database).LoadWallet(this);
+ DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
if (nLoadWalletRet == DBErrors::NEED_REWRITE)
{
- if (database->Rewrite("\x04pool"))
+ if (GetDatabase().Rewrite("\x04pool"))
{
for (const auto& spk_man_pair : m_spk_managers) {
spk_man_pair.second->RewriteDB();
@@ -3219,7 +3209,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
{
AssertLockHeld(cs_wallet);
- DBErrors nZapSelectTxRet = WalletBatch(*database).ZapSelectTx(vHashIn, vHashOut);
+ DBErrors nZapSelectTxRet = WalletBatch(GetDatabase()).ZapSelectTx(vHashIn, vHashOut);
for (const uint256& hash : vHashOut) {
const auto& it = mapWallet.find(hash);
wtxOrdered.erase(it->second.m_it_wtxOrdered);
@@ -3231,7 +3221,7 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
if (nZapSelectTxRet == DBErrors::NEED_REWRITE)
{
- if (database->Rewrite("\x04pool"))
+ if (GetDatabase().Rewrite("\x04pool"))
{
for (const auto& spk_man_pair : m_spk_managers) {
spk_man_pair.second->RewriteDB();
@@ -3269,14 +3259,14 @@ bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& add
bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& strPurpose)
{
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
return SetAddressBookWithDB(batch, address, strName, strPurpose);
}
bool CWallet::DelAddressBook(const CTxDestination& address)
{
bool is_mine;
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
{
LOCK(cs_wallet);
// If we want to delete receiving addresses, we need to take care that DestData "used" (and possibly newer DestData) gets preserved (and the "deleted" address transformed into a change entry instead of actually being deleted)
@@ -4023,7 +4013,7 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
int rescan_height = 0;
if (!gArgs.GetBoolArg("-rescan", false))
{
- WalletBatch batch(*walletInstance->database);
+ WalletBatch batch(walletInstance->GetDatabase());
CBlockLocator locator;
if (batch.ReadBestBlock(locator)) {
if (const Optional<int> fork_height = chain.findLocatorFork(locator)) {
@@ -4073,9 +4063,7 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
if (!time_first_key || time < *time_first_key) time_first_key = time;
}
if (time_first_key) {
- if (Optional<int> first_block = chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
- rescan_height = *first_block;
- }
+ chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, FoundBlock().height(rescan_height));
}
{
@@ -4086,7 +4074,7 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
}
}
walletInstance->chainStateFlushed(chain.getTipLocator());
- walletInstance->database->IncrementUpdateCounter();
+ walletInstance->GetDatabase().IncrementUpdateCounter();
}
{
@@ -4117,36 +4105,33 @@ const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest
return &address_book_it->second;
}
-bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings)
+bool CWallet::UpgradeWallet(int version, bilingual_str& error)
{
int prev_version = GetVersion();
- int nMaxVersion = version;
- if (nMaxVersion == 0) // the -upgradewallet without argument case
- {
+ if (version == 0) {
WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
- nMaxVersion = FEATURE_LATEST;
- SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
+ version = FEATURE_LATEST;
} else {
- WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
+ WalletLogPrintf("Allowing wallet upgrade up to %i\n", version);
}
- if (nMaxVersion < GetVersion())
- {
- error = _("Cannot downgrade wallet");
+ if (version < prev_version) {
+ error = strprintf(_("Cannot downgrade wallet from version %i to version %i. Wallet version unchanged."), prev_version, version);
return false;
}
- SetMaxVersion(nMaxVersion);
LOCK(cs_wallet);
// Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
- int max_version = GetVersion();
- if (!CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
- error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.");
+ if (!CanSupportFeature(FEATURE_HD_SPLIT) && version >= FEATURE_HD_SPLIT && version < FEATURE_PRE_SPLIT_KEYPOOL) {
+ error = strprintf(_("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."), prev_version, version, FEATURE_PRE_SPLIT_KEYPOOL);
return false;
}
+ // Permanently upgrade to the version
+ SetMinVersion(GetClosestWalletFeature(version));
+
for (auto spk_man : GetActiveScriptPubKeyMans()) {
- if (!spk_man->Upgrade(prev_version, error)) {
+ if (!spk_man->Upgrade(prev_version, version, error)) {
return false;
}
}
@@ -4167,7 +4152,7 @@ void CWallet::postInitProcess()
bool CWallet::BackupWallet(const std::string& strDest) const
{
- return database->Backup(strDest);
+ return GetDatabase().Backup(strDest);
}
CKeyPool::CKeyPool()
@@ -4470,7 +4455,7 @@ void CWallet::SetupDescriptorScriptPubKeyMans()
void CWallet::AddActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal)
{
- WalletBatch batch(*database);
+ WalletBatch batch(GetDatabase());
if (!batch.WriteActiveScriptPubKeyMan(static_cast<uint8_t>(type), id, internal)) {
throw std::runtime_error(std::string(__func__) + ": writing active ScriptPubKeyMan id failed");
}
@@ -4510,7 +4495,7 @@ DescriptorScriptPubKeyMan* CWallet::GetDescriptorScriptPubKeyMan(const WalletDes
return nullptr;
}
-ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label)
+ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal)
{
if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
WalletLogPrintf("Cannot add WalletDescriptor to a non-descriptor wallet\n");
@@ -4555,7 +4540,10 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat
}
// Top up key pool, the manager will generate new scriptPubKeys internally
- new_spk_man->TopUp();
+ if (!new_spk_man->TopUp()) {
+ WalletLogPrintf("Could not top up scriptPubKeys\n");
+ return nullptr;
+ }
// Apply the label if necessary
// Note: we disable labels for ranged descriptors
@@ -4567,7 +4555,7 @@ ScriptPubKeyMan* CWallet::AddWalletDescriptor(WalletDescriptor& desc, const Flat
}
CTxDestination dest;
- if (ExtractDestination(script_pub_keys.at(0), dest)) {
+ if (!internal && ExtractDestination(script_pub_keys.at(0), dest)) {
SetAddressBook(dest, label, "receive");
}
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 245144a1c9..e6beb111fb 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -636,9 +636,6 @@ private:
//! the current wallet version: clients below this version are not able to load the wallet
int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE};
- //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
- int nWalletMaxVersion GUARDED_BY(cs_wallet) = FEATURE_BASE;
-
int64_t nNextResend = 0;
bool fBroadcastTransactions = false;
// Local time that the tip block was received. Used to schedule wallet rebroadcasts.
@@ -698,7 +695,7 @@ private:
std::string m_name;
/** Internal database handle. */
- std::unique_ptr<WalletDatabase> database;
+ std::unique_ptr<WalletDatabase> const m_database;
/**
* The following is used to keep track of how far behind the wallet is
@@ -732,14 +729,11 @@ public:
*/
mutable RecursiveMutex cs_wallet;
- /** Get database handle used by this wallet. Ideally this function would
- * not be necessary.
- */
- WalletDatabase& GetDBHandle()
+ WalletDatabase& GetDatabase() const override
{
- return *database;
+ assert(static_cast<bool>(m_database));
+ return *m_database;
}
- WalletDatabase& GetDatabase() override { return *database; }
/**
* Select a set of coins such that nValueRet >= nTargetValue and at least
@@ -761,7 +755,7 @@ public:
CWallet(interfaces::Chain* chain, const std::string& name, std::unique_ptr<WalletDatabase> database)
: m_chain(chain),
m_name(name),
- database(std::move(database))
+ m_database(std::move(database))
{
}
@@ -800,8 +794,8 @@ public:
const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! check whether we are allowed to upgrade (or already support) to the named feature
- bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
+ //! check whether we support the named feature
+ bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return IsFeatureSupported(nWalletVersion, wf); }
/**
* populate vCoins with vector of available COutputs.
@@ -853,7 +847,7 @@ public:
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
+ bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; return true; }
/**
* Adds a destination data tuple to the store, and saves it to disk
@@ -1076,11 +1070,8 @@ public:
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
- //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
- void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr, bool fExplicit = false) override;
-
- //! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
- bool SetMaxVersion(int nVersion);
+ //! signify that a particular wallet feature is now used.
+ void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr) override;
//! get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetVersion() const { LOCK(cs_wallet); return nWalletVersion; }
@@ -1201,7 +1192,7 @@ public:
};
/** Upgrade the wallet */
- bool UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings);
+ bool UpgradeWallet(int version, bilingual_str& error);
//! Returns all unique ScriptPubKeyMans in m_internal_spk_managers and m_external_spk_managers
std::set<ScriptPubKeyMan*> GetActiveScriptPubKeyMans() const;
@@ -1280,7 +1271,7 @@ public:
DescriptorScriptPubKeyMan* GetDescriptorScriptPubKeyMan(const WalletDescriptor& desc) const;
//! Add a descriptor to the wallet, return a ScriptPubKeyMan & associated output type
- ScriptPubKeyMan* AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label);
+ ScriptPubKeyMan* AddWalletDescriptor(WalletDescriptor& desc, const FlatSigningProvider& signing_provider, const std::string& label, bool internal);
};
/**
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 0092a29cb4..5b72a01939 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -14,8 +14,12 @@
#include <util/system.h>
#include <util/time.h>
#include <util/translation.h>
+#ifdef USE_BDB
#include <wallet/bdb.h>
+#endif
+#ifdef USE_SQLITE
#include <wallet/sqlite.h>
+#endif
#include <wallet/wallet.h>
#include <atomic>
@@ -360,7 +364,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{
ssValue >> hash;
}
- catch (...) {}
+ catch (const std::ios_base::failure&) {}
bool fSkipCheck = false;
@@ -941,7 +945,7 @@ void MaybeCompactWalletDB()
}
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
- WalletDatabase& dbh = pwallet->GetDBHandle();
+ WalletDatabase& dbh = pwallet->GetDatabase();
unsigned int nUpdateCounter = dbh.nUpdateCounter;
@@ -1009,10 +1013,10 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
Optional<DatabaseFormat> format;
if (exists) {
- if (ExistsBerkeleyDatabase(path)) {
+ if (IsBDBFile(BDBDataFile(path))) {
format = DatabaseFormat::BERKELEY;
}
- if (ExistsSQLiteDatabase(path)) {
+ if (IsSQLiteFile(SQLiteDataFile(path))) {
if (format) {
error = Untranslated(strprintf("Failed to load database path '%s'. Data is in ambiguous format.", path.string()));
status = DatabaseStatus::FAILED_BAD_FORMAT;
@@ -1048,11 +1052,31 @@ std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const Databas
// Format is not set when a db doesn't already exist, so use the format specified by the options if it is set.
if (!format && options.require_format) format = options.require_format;
- if (format && format == DatabaseFormat::SQLITE) {
+ // If the format is not specified or detected, choose the default format based on what is available. We prefer BDB over SQLite for now.
+ if (!format) {
+#ifdef USE_SQLITE
+ format = DatabaseFormat::SQLITE;
+#endif
+#ifdef USE_BDB
+ format = DatabaseFormat::BERKELEY;
+#endif
+ }
+
+ if (format == DatabaseFormat::SQLITE) {
+#ifdef USE_SQLITE
return MakeSQLiteDatabase(path, options, status, error);
+#endif
+ error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support SQLite database format.", path.string()));
+ status = DatabaseStatus::FAILED_BAD_FORMAT;
+ return nullptr;
}
+#ifdef USE_BDB
return MakeBerkeleyDatabase(path, options, status, error);
+#endif
+ error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support Berkeley DB database format.", path.string()));
+ status = DatabaseStatus::FAILED_BAD_FORMAT;
+ return nullptr;
}
/** Return object for accessing dummy database with no read/write capabilities. */
@@ -1064,5 +1088,9 @@ std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase()
/** Return object for accessing temporary in-memory database. */
std::unique_ptr<WalletDatabase> CreateMockWalletDatabase()
{
+#ifdef USE_BDB
return MakeUnique<BerkeleyDatabase>(std::make_shared<BerkeleyEnvironment>(), "");
+#elif USE_SQLITE
+ return MakeUnique<SQLiteDatabase>("", "", true);
+#endif
}
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 7f1b86e458..e7b2d7d780 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -8,7 +8,6 @@
#include <amount.h>
#include <script/sign.h>
-#include <wallet/bdb.h>
#include <wallet/db.h>
#include <wallet/walletutil.h>
#include <key.h>
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
index 4452840eb1..fda9025588 100644
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -21,30 +21,27 @@ static void WalletToolReleaseWallet(CWallet* wallet)
delete wallet;
}
-static void WalletCreate(CWallet* wallet_instance)
+static void WalletCreate(CWallet* wallet_instance, uint64_t wallet_creation_flags)
{
LOCK(wallet_instance->cs_wallet);
wallet_instance->SetMinVersion(FEATURE_HD_SPLIT);
+ wallet_instance->AddWalletFlags(wallet_creation_flags);
- // generate a new HD seed
- auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
- CPubKey seed = spk_man->GenerateNewSeed();
- spk_man->SetHDSeed(seed);
+ if (!wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
+ auto spk_man = wallet_instance->GetOrCreateLegacyScriptPubKeyMan();
+ spk_man->SetupGeneration(false);
+ } else {
+ wallet_instance->SetupDescriptorScriptPubKeyMans();
+ }
tfm::format(std::cout, "Topping up keypool...\n");
wallet_instance->TopUpKeyPool();
}
-static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, bool create)
+static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::path& path, DatabaseOptions options)
{
- DatabaseOptions options;
DatabaseStatus status;
- if (create) {
- options.require_create = true;
- } else {
- options.require_existing = true;
- }
bilingual_str error;
std::unique_ptr<WalletDatabase> database = MakeDatabase(path, options, status, error);
if (!database) {
@@ -85,7 +82,7 @@ static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::pa
}
}
- if (create) WalletCreate(wallet_instance.get());
+ if (options.require_create) WalletCreate(wallet_instance.get(), options.create_flags);
return wallet_instance;
}
@@ -95,6 +92,9 @@ static void WalletShowInfo(CWallet* wallet_instance)
LOCK(wallet_instance->cs_wallet);
tfm::format(std::cout, "Wallet info\n===========\n");
+ tfm::format(std::cout, "Name: %s\n", wallet_instance->GetName());
+ tfm::format(std::cout, "Format: %s\n", wallet_instance->GetDatabase().Format());
+ tfm::format(std::cout, "Descriptors: %s\n", wallet_instance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) ? "yes" : "no");
tfm::format(std::cout, "Encrypted: %s\n", wallet_instance->IsCrypted() ? "yes" : "no");
tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no");
tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize());
@@ -107,18 +107,28 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
fs::path path = fs::absolute(name, GetWalletDir());
if (command == "create") {
- std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ true);
+ DatabaseOptions options;
+ options.require_create = true;
+ if (gArgs.GetBoolArg("-descriptors", false)) {
+ options.create_flags |= WALLET_FLAG_DESCRIPTORS;
+ options.require_format = DatabaseFormat::SQLITE;
+ }
+
+ std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
if (wallet_instance) {
WalletShowInfo(wallet_instance.get());
wallet_instance->Close();
}
} else if (command == "info" || command == "salvage") {
if (command == "info") {
- std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, /* create= */ false);
+ DatabaseOptions options;
+ options.require_existing = true;
+ std::shared_ptr<CWallet> wallet_instance = MakeWallet(name, path, options);
if (!wallet_instance) return false;
WalletShowInfo(wallet_instance.get());
wallet_instance->Close();
} else if (command == "salvage") {
+#ifdef USE_BDB
bilingual_str error;
std::vector<bilingual_str> warnings;
bool ret = RecoverDatabaseFile(path, error, warnings);
@@ -131,6 +141,10 @@ bool ExecuteWalletToolFunc(const std::string& command, const std::string& name)
}
}
return ret;
+#else
+ tfm::format(std::cerr, "Salvage command is not available as BDB support is not compiled");
+ return false;
+#endif
}
} else {
tfm::format(std::cerr, "Invalid command: %s\n", command);
diff --git a/src/wallet/walletutil.cpp b/src/wallet/walletutil.cpp
index a2a55f9751..16ddad3a84 100644
--- a/src/wallet/walletutil.cpp
+++ b/src/wallet/walletutil.cpp
@@ -7,9 +7,6 @@
#include <logging.h>
#include <util/system.h>
-bool ExistsBerkeleyDatabase(const fs::path& path);
-bool ExistsSQLiteDatabase(const fs::path& path);
-
fs::path GetWalletDir()
{
fs::path path;
@@ -32,41 +29,16 @@ fs::path GetWalletDir()
return path;
}
-std::vector<fs::path> ListWalletDir()
+bool IsFeatureSupported(int wallet_version, int feature_version)
{
- const fs::path wallet_dir = GetWalletDir();
- const size_t offset = wallet_dir.string().size() + 1;
- std::vector<fs::path> paths;
- boost::system::error_code ec;
-
- for (auto it = fs::recursive_directory_iterator(wallet_dir, ec); it != fs::recursive_directory_iterator(); it.increment(ec)) {
- if (ec) {
- LogPrintf("%s: %s %s\n", __func__, ec.message(), it->path().string());
- continue;
- }
-
- // Get wallet path relative to walletdir by removing walletdir from the wallet path.
- // This can be replaced by boost::filesystem::lexically_relative once boost is bumped to 1.60.
- const fs::path path = it->path().string().substr(offset);
+ return wallet_version >= feature_version;
+}
- if (it->status().type() == fs::directory_file &&
- (ExistsBerkeleyDatabase(it->path()) || ExistsSQLiteDatabase(it->path()))) {
- // Found a directory which contains wallet.dat btree file, add it as a wallet.
- paths.emplace_back(path);
- } else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && ExistsBerkeleyDatabase(it->path())) {
- if (it->path().filename() == "wallet.dat") {
- // Found top-level wallet.dat btree file, add top level directory ""
- // as a wallet.
- paths.emplace_back();
- } else {
- // Found top-level btree file not called wallet.dat. Current bitcoin
- // software will never create these files but will allow them to be
- // opened in a shared database environment for backwards compatibility.
- // Add it to the list of available wallets.
- paths.emplace_back(path);
- }
- }
+WalletFeature GetClosestWalletFeature(int version)
+{
+ static constexpr std::array wallet_features{FEATURE_LATEST, FEATURE_PRE_SPLIT_KEYPOOL, FEATURE_NO_DEFAULT_KEY, FEATURE_HD_SPLIT, FEATURE_HD, FEATURE_COMPRPUBKEY, FEATURE_WALLETCRYPT, FEATURE_BASE};
+ for (const WalletFeature& wf : wallet_features) {
+ if (version >= wf) return wf;
}
-
- return paths;
+ return static_cast<WalletFeature>(0);
}
diff --git a/src/wallet/walletutil.h b/src/wallet/walletutil.h
index afdcb2e18a..d4143ceff4 100644
--- a/src/wallet/walletutil.h
+++ b/src/wallet/walletutil.h
@@ -29,7 +29,8 @@ enum WalletFeature
FEATURE_LATEST = FEATURE_PRE_SPLIT_KEYPOOL
};
-
+bool IsFeatureSupported(int wallet_version, int feature_version);
+WalletFeature GetClosestWalletFeature(int version);
enum WalletFlags : uint64_t {
// wallet flags in the upper section (> 1 << 31) will lead to not opening the wallet if flag is unknown
@@ -64,9 +65,6 @@ enum WalletFlags : uint64_t {
//! Get the path of the wallet directory.
fs::path GetWalletDir();
-//! Get wallets in wallet directory.
-std::vector<fs::path> ListWalletDir();
-
/** Descriptor with some wallet metadata */
class WalletDescriptor
{
diff --git a/src/warnings.cpp b/src/warnings.cpp
index 501bf7e637..1dec663a73 100644
--- a/src/warnings.cpp
+++ b/src/warnings.cpp
@@ -14,7 +14,6 @@
static Mutex g_warnings_mutex;
static bilingual_str g_misc_warnings GUARDED_BY(g_warnings_mutex);
-static bool fLargeWorkForkFound GUARDED_BY(g_warnings_mutex) = false;
static bool fLargeWorkInvalidChainFound GUARDED_BY(g_warnings_mutex) = false;
void SetMiscWarning(const bilingual_str& warning)
@@ -23,18 +22,6 @@ void SetMiscWarning(const bilingual_str& warning)
g_misc_warnings = warning;
}
-void SetfLargeWorkForkFound(bool flag)
-{
- LOCK(g_warnings_mutex);
- fLargeWorkForkFound = flag;
-}
-
-bool GetfLargeWorkForkFound()
-{
- LOCK(g_warnings_mutex);
- return fLargeWorkForkFound;
-}
-
void SetfLargeWorkInvalidChainFound(bool flag)
{
LOCK(g_warnings_mutex);
@@ -60,10 +47,7 @@ bilingual_str GetWarnings(bool verbose)
warnings_verbose.emplace_back(warnings_concise);
}
- if (fLargeWorkForkFound) {
- warnings_concise = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
- warnings_verbose.emplace_back(warnings_concise);
- } else if (fLargeWorkInvalidChainFound) {
+ if (fLargeWorkInvalidChainFound) {
warnings_concise = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
warnings_verbose.emplace_back(warnings_concise);
}
diff --git a/src/warnings.h b/src/warnings.h
index 28546eb753..e87b64a86d 100644
--- a/src/warnings.h
+++ b/src/warnings.h
@@ -11,8 +11,6 @@
struct bilingual_str;
void SetMiscWarning(const bilingual_str& warning);
-void SetfLargeWorkForkFound(bool flag);
-bool GetfLargeWorkForkFound();
void SetfLargeWorkInvalidChainFound(bool flag);
/** Format a string that describes several potential problems detected by the core.
* @param[in] verbose bool
diff --git a/test/config.ini.in b/test/config.ini.in
index be1bfe8752..77c9a720c3 100644
--- a/test/config.ini.in
+++ b/test/config.ini.in
@@ -16,6 +16,8 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
[components]
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
@ENABLE_WALLET_TRUE@ENABLE_WALLET=true
+@USE_SQLITE_TRUE@USE_SQLITE=true
+@USE_BDB_TRUE@USE_BDB=true
@BUILD_BITCOIN_CLI_TRUE@ENABLE_CLI=true
@BUILD_BITCOIN_WALLET_TRUE@ENABLE_WALLET_TOOL=true
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
diff --git a/test/functional/README.md b/test/functional/README.md
index 82b30fed51..2764acbf18 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -34,7 +34,7 @@ don't have test cases for.
- When subclassing the BitcoinTestFramework, place overrides for the
`set_test_params()`, `add_options()` and `setup_xxxx()` methods at the top of
the subclass, then locally-defined helper methods, then the `run_test()` method.
-- Use `'{}'.format(x)` for string formatting, not `'%s' % x`.
+- Use `f'{x}'` for string formatting in preference to `'{}'.format(x)` or `'%s' % x`.
#### Naming guidelines
diff --git a/test/functional/data/wallets/high_minversion/.walletlock b/test/functional/data/wallets/high_minversion/.walletlock
deleted file mode 100644
index e69de29bb2..0000000000
--- a/test/functional/data/wallets/high_minversion/.walletlock
+++ /dev/null
diff --git a/test/functional/data/wallets/high_minversion/GENERATE.md b/test/functional/data/wallets/high_minversion/GENERATE.md
deleted file mode 100644
index e55c4557ca..0000000000
--- a/test/functional/data/wallets/high_minversion/GENERATE.md
+++ /dev/null
@@ -1,8 +0,0 @@
-The wallet has been created by starting Bitcoin Core with the options
-`-regtest -datadir=/tmp -nowallet -walletdir=$(pwd)/test/functional/data/wallets/`.
-
-In the source code, `WalletFeature::FEATURE_LATEST` has been modified to be large, so that the minversion is too high
-for a current build of the wallet.
-
-The wallet has then been created with the RPC `createwallet high_minversion true true`, so that a blank wallet with
-private keys disabled is created.
diff --git a/test/functional/data/wallets/high_minversion/db.log b/test/functional/data/wallets/high_minversion/db.log
deleted file mode 100644
index e69de29bb2..0000000000
--- a/test/functional/data/wallets/high_minversion/db.log
+++ /dev/null
diff --git a/test/functional/data/wallets/high_minversion/wallet.dat b/test/functional/data/wallets/high_minversion/wallet.dat
deleted file mode 100644
index 99ab809263..0000000000
--- a/test/functional/data/wallets/high_minversion/wallet.dat
+++ /dev/null
Binary files differ
diff --git a/test/functional/example_test.py b/test/functional/example_test.py
index 3b9bd3048f..c28bb7115f 100755
--- a/test/functional/example_test.py
+++ b/test/functional/example_test.py
@@ -25,7 +25,6 @@ from test_framework.p2p import (
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
)
# P2PInterface is a class containing callbacks to be executed when a P2P
@@ -115,7 +114,7 @@ class ExampleTest(BitcoinTestFramework):
# In this test, we're not connecting node2 to node0 or node1. Calls to
# sync_all() should not include node2, since we're not expecting it to
# sync.
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_all(self.nodes[0:2])
# Use setup_nodes() to customize the node start behaviour (for example if
@@ -183,7 +182,7 @@ class ExampleTest(BitcoinTestFramework):
self.nodes[1].waitforblockheight(11)
self.log.info("Connect node2 and node1")
- connect_nodes(self.nodes[1], 2)
+ self.connect_nodes(1, 2)
self.log.info("Wait for node2 to receive all the blocks from node1")
self.sync_all()
diff --git a/test/functional/feature_abortnode.py b/test/functional/feature_abortnode.py
index 17fbf50cc8..8abfdef3a1 100755
--- a/test/functional/feature_abortnode.py
+++ b/test/functional/feature_abortnode.py
@@ -11,7 +11,7 @@
"""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import get_datadir_path, connect_nodes
+from test_framework.util import get_datadir_path
import os
@@ -36,7 +36,7 @@ class AbortNodeTest(BitcoinTestFramework):
# attempt.
self.nodes[1].generate(3)
with self.nodes[0].assert_debug_log(["Failed to disconnect block"]):
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.nodes[1].generate(1)
# Check that node0 aborted
diff --git a/test/functional/feature_backwards_compatibility.py b/test/functional/feature_backwards_compatibility.py
index 21776d85c9..b161c71a85 100755
--- a/test/functional/feature_backwards_compatibility.py
+++ b/test/functional/feature_backwards_compatibility.py
@@ -27,6 +27,7 @@ from test_framework.descriptors import descsum_create
from test_framework.util import (
assert_equal,
+ assert_raises_rpc_error,
)
@@ -82,7 +83,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
# w1: regular wallet, created on master: update this test when default
# wallets can no longer be opened by older versions.
- node_master.rpc.createwallet(wallet_name="w1")
+ node_master.createwallet(wallet_name="w1")
wallet = node_master.get_wallet_rpc("w1")
info = wallet.getwalletinfo()
assert info['private_keys_enabled']
@@ -127,7 +128,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
# w2: wallet with private keys disabled, created on master: update this
# test when default wallets private keys disabled can no longer be
# opened by older versions.
- node_master.rpc.createwallet(wallet_name="w2", disable_private_keys=True)
+ node_master.createwallet(wallet_name="w2", disable_private_keys=True)
wallet = node_master.get_wallet_rpc("w2")
info = wallet.getwalletinfo()
assert info['private_keys_enabled'] == False
@@ -149,7 +150,7 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
# w3: blank wallet, created on master: update this
# test when default blank wallets can no longer be opened by older versions.
- node_master.rpc.createwallet(wallet_name="w3", blank=True)
+ node_master.createwallet(wallet_name="w3", blank=True)
wallet = node_master.get_wallet_rpc("w3")
info = wallet.getwalletinfo()
assert info['private_keys_enabled']
@@ -215,67 +216,89 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
os.path.join(node_v19_wallets_dir, wallet)
)
- # Open the wallets in v0.19
- node_v19.loadwallet("w1")
- wallet = node_v19.get_wallet_rpc("w1")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled']
- assert info['keypoolsize'] > 0
- txs = wallet.listtransactions()
- assert_equal(len(txs), 5)
- assert_equal(txs[1]["txid"], tx1_id)
- assert_equal(txs[2]["walletconflicts"], [tx1_id])
- assert_equal(txs[1]["replaced_by_txid"], tx2_id)
- assert not(txs[1]["abandoned"])
- assert_equal(txs[1]["confirmations"], -1)
- assert_equal(txs[2]["blockindex"], 1)
- assert txs[3]["abandoned"]
- assert_equal(txs[4]["walletconflicts"], [tx3_id])
- assert_equal(txs[3]["replaced_by_txid"], tx4_id)
- assert not(hasattr(txs[3], "blockindex"))
-
- node_v19.loadwallet("w2")
- wallet = node_v19.get_wallet_rpc("w2")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled'] == False
- assert info['keypoolsize'] == 0
-
- node_v19.loadwallet("w3")
- wallet = node_v19.get_wallet_rpc("w3")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled']
- assert info['keypoolsize'] == 0
-
- # Open the wallets in v0.18
- node_v18.loadwallet("w1")
- wallet = node_v18.get_wallet_rpc("w1")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled']
- assert info['keypoolsize'] > 0
- txs = wallet.listtransactions()
- assert_equal(len(txs), 5)
- assert_equal(txs[1]["txid"], tx1_id)
- assert_equal(txs[2]["walletconflicts"], [tx1_id])
- assert_equal(txs[1]["replaced_by_txid"], tx2_id)
- assert not(txs[1]["abandoned"])
- assert_equal(txs[1]["confirmations"], -1)
- assert_equal(txs[2]["blockindex"], 1)
- assert txs[3]["abandoned"]
- assert_equal(txs[4]["walletconflicts"], [tx3_id])
- assert_equal(txs[3]["replaced_by_txid"], tx4_id)
- assert not(hasattr(txs[3], "blockindex"))
-
- node_v18.loadwallet("w2")
- wallet = node_v18.get_wallet_rpc("w2")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled'] == False
- assert info['keypoolsize'] == 0
-
- node_v18.loadwallet("w3")
- wallet = node_v18.get_wallet_rpc("w3")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled']
- assert info['keypoolsize'] == 0
+ if not self.options.descriptors:
+ # Descriptor wallets break compatibility, only run this test for legacy wallet
+ # Open the wallets in v0.19
+ node_v19.loadwallet("w1")
+ wallet = node_v19.get_wallet_rpc("w1")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] > 0
+ txs = wallet.listtransactions()
+ assert_equal(len(txs), 5)
+ assert_equal(txs[1]["txid"], tx1_id)
+ assert_equal(txs[2]["walletconflicts"], [tx1_id])
+ assert_equal(txs[1]["replaced_by_txid"], tx2_id)
+ assert not(txs[1]["abandoned"])
+ assert_equal(txs[1]["confirmations"], -1)
+ assert_equal(txs[2]["blockindex"], 1)
+ assert txs[3]["abandoned"]
+ assert_equal(txs[4]["walletconflicts"], [tx3_id])
+ assert_equal(txs[3]["replaced_by_txid"], tx4_id)
+ assert not(hasattr(txs[3], "blockindex"))
+
+ node_v19.loadwallet("w2")
+ wallet = node_v19.get_wallet_rpc("w2")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled'] == False
+ assert info['keypoolsize'] == 0
+
+ node_v19.loadwallet("w3")
+ wallet = node_v19.get_wallet_rpc("w3")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] == 0
+
+ # Open the wallets in v0.18
+ node_v18.loadwallet("w1")
+ wallet = node_v18.get_wallet_rpc("w1")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] > 0
+ txs = wallet.listtransactions()
+ assert_equal(len(txs), 5)
+ assert_equal(txs[1]["txid"], tx1_id)
+ assert_equal(txs[2]["walletconflicts"], [tx1_id])
+ assert_equal(txs[1]["replaced_by_txid"], tx2_id)
+ assert not(txs[1]["abandoned"])
+ assert_equal(txs[1]["confirmations"], -1)
+ assert_equal(txs[2]["blockindex"], 1)
+ assert txs[3]["abandoned"]
+ assert_equal(txs[4]["walletconflicts"], [tx3_id])
+ assert_equal(txs[3]["replaced_by_txid"], tx4_id)
+ assert not(hasattr(txs[3], "blockindex"))
+
+ node_v18.loadwallet("w2")
+ wallet = node_v18.get_wallet_rpc("w2")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled'] == False
+ assert info['keypoolsize'] == 0
+
+ node_v18.loadwallet("w3")
+ wallet = node_v18.get_wallet_rpc("w3")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] == 0
+
+ node_v17.loadwallet("w1")
+ wallet = node_v17.get_wallet_rpc("w1")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled']
+ assert info['keypoolsize'] > 0
+
+ node_v17.loadwallet("w2")
+ wallet = node_v17.get_wallet_rpc("w2")
+ info = wallet.getwalletinfo()
+ assert info['private_keys_enabled'] == False
+ assert info['keypoolsize'] == 0
+ else:
+ # Descriptor wallets appear to be corrupted wallets to old software
+ assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node_v19.loadwallet, "w1")
+ assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node_v19.loadwallet, "w2")
+ assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node_v19.loadwallet, "w3")
+ assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node_v18.loadwallet, "w1")
+ assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node_v18.loadwallet, "w2")
+ assert_raises_rpc_error(-4, "Wallet file verification failed: wallet.dat corrupt, salvage failed", node_v18.loadwallet, "w3")
# Open the wallets in v0.17
node_v17.loadwallet("w1_v18")
@@ -284,24 +307,12 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
assert info['private_keys_enabled']
assert info['keypoolsize'] > 0
- node_v17.loadwallet("w1")
- wallet = node_v17.get_wallet_rpc("w1")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled']
- assert info['keypoolsize'] > 0
-
node_v17.loadwallet("w2_v18")
wallet = node_v17.get_wallet_rpc("w2_v18")
info = wallet.getwalletinfo()
assert info['private_keys_enabled'] == False
assert info['keypoolsize'] == 0
- node_v17.loadwallet("w2")
- wallet = node_v17.get_wallet_rpc("w2")
- info = wallet.getwalletinfo()
- assert info['private_keys_enabled'] == False
- assert info['keypoolsize'] == 0
-
# RPC loadwallet failure causes bitcoind to exit, in addition to the RPC
# call failure, so the following test won't work:
# assert_raises_rpc_error(-4, "Wallet loading failed.", node_v17.loadwallet, 'w3_v18')
@@ -309,14 +320,22 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
# Instead, we stop node and try to launch it with the wallet:
self.stop_node(4)
node_v17.assert_start_raises_init_error(["-wallet=w3_v18"], "Error: Error loading w3_v18: Wallet requires newer version of Bitcoin Core")
- node_v17.assert_start_raises_init_error(["-wallet=w3"], "Error: Error loading w3: Wallet requires newer version of Bitcoin Core")
+ if self.options.descriptors:
+ # Descriptor wallets appear to be corrupted wallets to old software
+ node_v17.assert_start_raises_init_error(["-wallet=w1"], "Error: wallet.dat corrupt, salvage failed")
+ node_v17.assert_start_raises_init_error(["-wallet=w2"], "Error: wallet.dat corrupt, salvage failed")
+ node_v17.assert_start_raises_init_error(["-wallet=w3"], "Error: wallet.dat corrupt, salvage failed")
+ else:
+ node_v17.assert_start_raises_init_error(["-wallet=w3"], "Error: Error loading w3: Wallet requires newer version of Bitcoin Core")
self.start_node(4)
- # Open most recent wallet in v0.16 (no loadwallet RPC)
- self.restart_node(5, extra_args=["-wallet=w2"])
- wallet = node_v16.get_wallet_rpc("w2")
- info = wallet.getwalletinfo()
- assert info['keypoolsize'] == 1
+ if not self.options.descriptors:
+ # Descriptor wallets break compatibility, only run this test for legacy wallets
+ # Open most recent wallet in v0.16 (no loadwallet RPC)
+ self.restart_node(5, extra_args=["-wallet=w2"])
+ wallet = node_v16.get_wallet_rpc("w2")
+ info = wallet.getwalletinfo()
+ assert info['keypoolsize'] == 1
# Create upgrade wallet in v0.16
self.restart_node(-1, extra_args=["-wallet=u1_v16"])
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py
index 1253c45418..60492350ee 100755
--- a/test/functional/feature_bip68_sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -6,7 +6,7 @@
import time
-from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment
+from test_framework.blocktools import create_block, NORMAL_GBT_REQUEST_PARAMS, add_witness_commitment
from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut, FromHex, ToHex
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -275,6 +275,8 @@ class BIP68Test(BitcoinTestFramework):
# Advance the time on the node so that we can test timelocks
self.nodes[0].setmocktime(cur_time+600)
+ # Save block template now to use for the reorg later
+ tmpl = self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
self.nodes[0].generate(1)
assert tx2.hash not in self.nodes[0].getrawmempool()
@@ -318,16 +320,15 @@ class BIP68Test(BitcoinTestFramework):
# diagram above).
# This would cause tx2 to be added back to the mempool, which in turn causes
# tx3 to be removed.
- tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount()-1), 16)
- height = self.nodes[0].getblockcount()
for i in range(2):
- block = create_block(tip, create_coinbase(height), cur_time)
- block.nVersion = 3
+ block = create_block(tmpl=tmpl, ntime=cur_time)
block.rehash()
block.solve()
tip = block.sha256
- height += 1
assert_equal(None if i == 1 else 'inconclusive', self.nodes[0].submitblock(ToHex(block)))
+ tmpl = self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
+ tmpl['previousblockhash'] = '%x' % tip
+ tmpl['transactions'] = []
cur_time += 1
mempool = self.nodes[0].getrawmempool()
@@ -375,9 +376,7 @@ class BIP68Test(BitcoinTestFramework):
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx3))
# make a block that violates bip68; ensure that the tip updates
- tip = int(self.nodes[0].getbestblockhash(), 16)
- block = create_block(tip, create_coinbase(self.nodes[0].getblockcount()+1))
- block.nVersion = 3
+ block = create_block(tmpl=self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS))
block.vtx.extend([tx1, tx2, tx3])
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 19753d73ef..158efb52c9 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -119,7 +119,7 @@ class FullBlockTest(BitcoinTestFramework):
# Allow the block to mature
blocks = []
for i in range(NUM_BUFFER_BLOCKS_TO_GENERATE):
- blocks.append(self.next_block("maturitybuffer.{}".format(i)))
+ blocks.append(self.next_block(f"maturitybuffer.{i}"))
self.save_spendable_output()
self.send_blocks(blocks)
@@ -151,8 +151,8 @@ class FullBlockTest(BitcoinTestFramework):
if template.valid_in_block:
continue
- self.log.info("Reject block with invalid tx: %s", TxTemplate.__name__)
- blockname = "for_invalid.%s" % TxTemplate.__name__
+ self.log.info(f"Reject block with invalid tx: {TxTemplate.__name__}")
+ blockname = f"for_invalid.{TxTemplate.__name__}"
badblock = self.next_block(blockname)
badtx = template.get_tx()
if TxTemplate != invalid_txs.InputMissing:
@@ -1251,7 +1251,7 @@ class FullBlockTest(BitcoinTestFramework):
blocks = []
spend = out[32]
for i in range(89, LARGE_REORG_SIZE + 89):
- b = self.next_block(i, spend, version=4)
+ b = self.next_block(i, spend)
tx = CTransaction()
script_length = MAX_BLOCK_BASE_SIZE - len(b.serialize()) - 69
script_output = CScript([b'\x00' * script_length])
@@ -1270,18 +1270,18 @@ class FullBlockTest(BitcoinTestFramework):
self.move_tip(88)
blocks2 = []
for i in range(89, LARGE_REORG_SIZE + 89):
- blocks2.append(self.next_block("alt" + str(i), version=4))
+ blocks2.append(self.next_block("alt" + str(i)))
self.send_blocks(blocks2, False, force_send=True)
# extend alt chain to trigger re-org
- block = self.next_block("alt" + str(chain1_tip + 1), version=4)
+ block = self.next_block("alt" + str(chain1_tip + 1))
self.send_blocks([block], True, timeout=2440)
# ... and re-org back to the first chain
self.move_tip(chain1_tip)
- block = self.next_block(chain1_tip + 1, version=4)
+ block = self.next_block(chain1_tip + 1)
self.send_blocks([block], False, force_send=True)
- block = self.next_block(chain1_tip + 2, version=4)
+ block = self.next_block(chain1_tip + 2)
self.send_blocks([block], True, timeout=2440)
self.log.info("Reject a block with an invalid block header version")
@@ -1289,7 +1289,7 @@ class FullBlockTest(BitcoinTestFramework):
self.send_blocks([b_v1], success=False, force_send=True, reject_reason='bad-version(0x00000001)', reconnect=True)
self.move_tip(chain1_tip + 2)
- b_cb34 = self.next_block('b_cb34', version=4)
+ b_cb34 = self.next_block('b_cb34')
b_cb34.vtx[0].vin[0].scriptSig = b_cb34.vtx[0].vin[0].scriptSig[:-1]
b_cb34.vtx[0].rehash()
b_cb34.hashMerkleRoot = b_cb34.calc_merkle_root()
@@ -1323,7 +1323,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.rehash()
return tx
- def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), *, version=1):
+ def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), *, version=4):
if self.tip is None:
base_block_hash = self.genesis_hash
block_time = int(time.time()) + 1
@@ -1355,12 +1355,12 @@ class FullBlockTest(BitcoinTestFramework):
# save the current tip so it can be spent by a later block
def save_spendable_output(self):
- self.log.debug("saving spendable output %s" % self.tip.vtx[0])
+ self.log.debug(f"saving spendable output {self.tip.vtx[0]}")
self.spendable_outputs.append(self.tip)
# get an output that we previously marked as spendable
def get_spendable_output(self):
- self.log.debug("getting spendable output %s" % self.spendable_outputs[0].vtx[0])
+ self.log.debug(f"getting spendable output {self.spendable_outputs[0].vtx[0]}")
return self.spendable_outputs.pop(0).vtx[0]
# move the tip back to a previous block
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index 60533e196f..3e28dae4b3 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -179,19 +179,15 @@ class ConfArgsTest(BitcoinTestFramework):
# Create the directory and ensure the config file now works
os.mkdir(new_data_dir)
- self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
+ self.start_node(0, ['-conf='+conf_file])
self.stop_node(0)
assert os.path.exists(os.path.join(new_data_dir, self.chain, 'blocks'))
- if self.is_wallet_compiled():
- assert os.path.exists(os.path.join(new_data_dir, self.chain, 'wallets', 'w1'))
# Ensure command line argument overrides datadir in conf
os.mkdir(new_data_dir_2)
self.nodes[0].datadir = new_data_dir_2
- self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
+ self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file])
assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'blocks'))
- if self.is_wallet_compiled():
- assert os.path.exists(os.path.join(new_data_dir_2, self.chain, 'wallets', 'w2'))
if __name__ == '__main__':
diff --git a/test/functional/feature_csv_activation.py b/test/functional/feature_csv_activation.py
index 39e8bca751..46ba18b9b5 100755
--- a/test/functional/feature_csv_activation.py
+++ b/test/functional/feature_csv_activation.py
@@ -150,7 +150,6 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.setup_clean_chain = True
self.extra_args = [[
'-whitelist=noban@127.0.0.1',
- '-blockversion=4',
'-addresstype=legacy',
'-par=1', # Use only one script thread to get the exact reject reason for testing
]]
diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py
index 702a1d9995..8f522aee66 100755
--- a/test/functional/feature_fee_estimation.py
+++ b/test/functional/feature_fee_estimation.py
@@ -13,7 +13,7 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_greater_than_or_equal,
- connect_nodes,
+ assert_raises_rpc_error,
satoshi_round,
)
@@ -232,9 +232,9 @@ class EstimateFeeTest(BitcoinTestFramework):
# so the estimates would not be affected by the splitting transactions
self.start_node(1)
self.start_node(2)
- connect_nodes(self.nodes[1], 0)
- connect_nodes(self.nodes[0], 2)
- connect_nodes(self.nodes[2], 1)
+ self.connect_nodes(1, 0)
+ self.connect_nodes(0, 2)
+ self.connect_nodes(2, 1)
self.sync_all()
@@ -263,6 +263,11 @@ class EstimateFeeTest(BitcoinTestFramework):
self.log.info("Final estimates after emptying mempools")
check_estimates(self.nodes[1], self.fees_per_kb)
+ self.log.info("Testing that fee estimation is disabled in blocksonly.")
+ self.restart_node(0, ["-blocksonly"])
+ assert_raises_rpc_error(-32603, "Fee estimation disabled",
+ self.nodes[0].estimatesmartfee, 2)
+
if __name__ == '__main__':
EstimateFeeTest().main()
diff --git a/test/functional/feature_minchainwork.py b/test/functional/feature_minchainwork.py
index dbff6f15f2..abf87e8f0c 100755
--- a/test/functional/feature_minchainwork.py
+++ b/test/functional/feature_minchainwork.py
@@ -18,7 +18,7 @@ only succeeds past a given node once its nMinimumChainWork has been exceeded.
import time
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import connect_nodes, assert_equal
+from test_framework.util import assert_equal
# 2 hashes required per regtest block (with no difficulty adjustment)
REGTEST_WORK_PER_BLOCK = 2
@@ -39,7 +39,7 @@ class MinimumChainWorkTest(BitcoinTestFramework):
# block relay to inbound peers.
self.setup_nodes()
for i in range(self.num_nodes-1):
- connect_nodes(self.nodes[i+1], i)
+ self.connect_nodes(i+1, i)
def run_test(self):
# Start building a chain on node0. node2 shouldn't be able to sync until node1's
diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py
index 5522f2b7c6..47bc8dbb49 100755
--- a/test/functional/feature_notifications.py
+++ b/test/functional/feature_notifications.py
@@ -9,8 +9,6 @@ from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE, keyhash_to_p2pkh
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
- disconnect_nodes,
hex_str_to_bytes,
)
@@ -41,11 +39,12 @@ class NotificationsTest(BitcoinTestFramework):
# -alertnotify and -blocknotify on node0, walletnotify on node1
self.extra_args = [[
- "-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')),
- "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
- ["-blockversion=211",
- "-rescan",
- "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s')))]]
+ "-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')),
+ "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s')),
+ ], [
+ "-rescan",
+ "-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, notify_outputname('%w', '%s'))),
+ ]]
self.wallet_names = [self.default_wallet_name, self.wallet]
super().setup_network()
@@ -75,7 +74,7 @@ class NotificationsTest(BitcoinTestFramework):
self.log.info("test -walletnotify after rescan")
# restart node to rescan to force wallet notifications
self.start_node(1)
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
@@ -126,12 +125,12 @@ class NotificationsTest(BitcoinTestFramework):
# Bump tx2 as bump2 and generate a block on node 0 while
# disconnected, then reconnect and check for notifications on node 1
# about newly confirmed bump2 and newly conflicted tx2.
- disconnect_nodes(self.nodes[0], 1)
+ self.disconnect_nodes(0, 1)
bump2 = self.nodes[0].bumpfee(tx2)["txid"]
self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE)
assert_equal(self.nodes[0].gettransaction(bump2)["confirmations"], 1)
assert_equal(tx2 in self.nodes[1].getrawmempool(), True)
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks()
self.expect_wallet_notify([bump2, tx2])
assert_equal(self.nodes[1].gettransaction(bump2)["confirmations"], 1)
diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py
index ff55cb76d9..b0eac7056b 100755
--- a/test/functional/feature_nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -14,7 +14,7 @@ Generate 427 more blocks.
"""
import time
-from test_framework.blocktools import create_coinbase, create_block, create_transaction, add_witness_commitment
+from test_framework.blocktools import NORMAL_GBT_REQUEST_PARAMS, create_block, create_transaction, add_witness_commitment
from test_framework.messages import CTransaction
from test_framework.script import CScript
from test_framework.test_framework import BitcoinTestFramework
@@ -37,23 +37,32 @@ def trueDummy(tx):
class NULLDUMMYTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 1
+ # Need two nodes only so GBT doesn't complain that it's not connected
+ self.num_nodes = 2
self.setup_clean_chain = True
# This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through
# normal segwit activation here (and don't use the default always-on behaviour).
self.extra_args = [[
'-segwitheight=432',
'-addresstype=legacy',
- ]]
+ ]] * 2
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def run_test(self):
- self.address = self.nodes[0].getnewaddress()
- self.ms_address = self.nodes[0].addmultisigaddress(1, [self.address])['address']
- self.wit_address = self.nodes[0].getnewaddress(address_type='p2sh-segwit')
- self.wit_ms_address = self.nodes[0].addmultisigaddress(1, [self.address], '', 'p2sh-segwit')['address']
+ 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 unnecssary (and does not need to be tested) for descriptor wallets
+ wmulti.importaddress(self.ms_address)
+ wmulti.importaddress(self.wit_ms_address)
self.coinbase_blocks = self.nodes[0].generate(2) # Block 2
coinbase_txid = []
@@ -61,7 +70,6 @@ class NULLDUMMYTest(BitcoinTestFramework):
coinbase_txid.append(self.nodes[0].getblock(i)['tx'][0])
self.nodes[0].generate(427) # Block 429
self.lastblockhash = self.nodes[0].getbestblockhash()
- self.tip = int("0x" + self.lastblockhash, 0)
self.lastblockheight = 429
self.lastblocktime = int(time.time()) + 429
@@ -102,8 +110,10 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.block_submit(self.nodes[0], test6txs, True, True)
def block_submit(self, node, txs, witness=False, accept=False):
- block = create_block(self.tip, create_coinbase(self.lastblockheight + 1), self.lastblocktime + 1)
- block.nVersion = 4
+ tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
+ assert_equal(tmpl['previousblockhash'], self.lastblockhash)
+ assert_equal(tmpl['height'], self.lastblockheight + 1)
+ block = create_block(tmpl=tmpl, ntime=self.lastblocktime + 1)
for tx in txs:
tx.rehash()
block.vtx.append(tx)
@@ -114,7 +124,6 @@ class NULLDUMMYTest(BitcoinTestFramework):
assert_equal(None if accept else 'block-validation-failed', node.submitblock(block.serialize().hex()))
if (accept):
assert_equal(node.getbestblockhash(), block.hash)
- self.tip = block.sha256
self.lastblockhash = block.hash
self.lastblocktime += 1
self.lastblockheight += 1
diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py
index be323d355e..05b658ed87 100755
--- a/test/functional/feature_proxy.py
+++ b/test/functional/feature_proxy.py
@@ -18,13 +18,16 @@ Test plan:
- proxy on IPv6
- Create various proxies (as threads)
-- Create bitcoinds that connect to them
-- Manipulate the bitcoinds using addnode (onetry) an observe effects
+- Create nodes that connect to them
+- Manipulate the peer connections using addnode (onetry) and observe effects
+- Test the getpeerinfo `network` field for the peer
addnode connect to IPv4
addnode connect to IPv6
addnode connect to onion
addnode connect to generic DNS name
+
+- Test getnetworkinfo for each node
"""
import socket
@@ -41,6 +44,16 @@ from test_framework.netutil import test_ipv6_local
RANGE_BEGIN = PORT_MIN + 2 * PORT_RANGE # Start after p2p and rpc ports
+# Networks returned by RPC getpeerinfo, defined in src/netbase.cpp::GetNetworkName()
+NET_UNROUTABLE = "unroutable"
+NET_IPV4 = "ipv4"
+NET_IPV6 = "ipv6"
+NET_ONION = "onion"
+
+# Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo()
+NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION})
+
+
class ProxyTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
@@ -77,23 +90,29 @@ class ProxyTest(BitcoinTestFramework):
self.serv3 = Socks5Server(self.conf3)
self.serv3.start()
- # Note: proxies are not used to connect to local nodes
- # this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost
+ # Note: proxies are not used to connect to local nodes. This is because the proxy to
+ # use is based on CService.GetNetwork(), which returns NET_UNROUTABLE for localhost.
args = [
['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
[]
- ]
+ ]
if self.have_ipv6:
args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
self.add_nodes(self.num_nodes, extra_args=args)
self.start_nodes()
+ def network_test(self, node, addr, network):
+ for peer in node.getpeerinfo():
+ if peer["addr"] == addr:
+ assert_equal(peer["network"], network)
+
def node_test(self, node, proxies, auth, test_onion=True):
rv = []
- # Test: outgoing IPv4 connection through node
- node.addnode("15.61.23.23:1234", "onetry")
+ addr = "15.61.23.23:1234"
+ self.log.debug("Test: outgoing IPv4 connection through node for address {}".format(addr))
+ node.addnode(addr, "onetry")
cmd = proxies[0].queue.get()
assert isinstance(cmd, Socks5Command)
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
@@ -104,10 +123,12 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(cmd.username, None)
assert_equal(cmd.password, None)
rv.append(cmd)
+ self.network_test(node, addr, network=NET_IPV4)
if self.have_ipv6:
- # Test: outgoing IPv6 connection through node
- node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
+ addr = "[1233:3432:2434:2343:3234:2345:6546:4534]:5443"
+ self.log.debug("Test: outgoing IPv6 connection through node for address {}".format(addr))
+ node.addnode(addr, "onetry")
cmd = proxies[1].queue.get()
assert isinstance(cmd, Socks5Command)
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
@@ -118,10 +139,12 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(cmd.username, None)
assert_equal(cmd.password, None)
rv.append(cmd)
+ self.network_test(node, addr, network=NET_IPV6)
if test_onion:
- # Test: outgoing onion connection through node
- node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
+ addr = "bitcoinostk4e4re.onion:8333"
+ self.log.debug("Test: outgoing onion connection through node for address {}".format(addr))
+ node.addnode(addr, "onetry")
cmd = proxies[2].queue.get()
assert isinstance(cmd, Socks5Command)
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
@@ -131,9 +154,11 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(cmd.username, None)
assert_equal(cmd.password, None)
rv.append(cmd)
+ self.network_test(node, addr, network=NET_ONION)
- # Test: outgoing DNS name connection through node
- node.addnode("node.noumenon:8333", "onetry")
+ addr = "node.noumenon:8333"
+ self.log.debug("Test: outgoing DNS name connection through node for address {}".format(addr))
+ node.addnode(addr, "onetry")
cmd = proxies[3].queue.get()
assert isinstance(cmd, Socks5Command)
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
@@ -143,6 +168,7 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(cmd.username, None)
assert_equal(cmd.password, None)
rv.append(cmd)
+ self.network_test(node, addr, network=NET_UNROUTABLE)
return rv
@@ -169,15 +195,17 @@ class ProxyTest(BitcoinTestFramework):
r[x['name']] = x
return r
- # test RPC getnetworkinfo
+ self.log.info("Test RPC getnetworkinfo")
n0 = networks_dict(self.nodes[0].getnetworkinfo())
- for net in ['ipv4','ipv6','onion']:
+ assert_equal(NETWORKS, n0.keys())
+ for net in NETWORKS:
assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr))
assert_equal(n0[net]['proxy_randomize_credentials'], True)
assert_equal(n0['onion']['reachable'], True)
n1 = networks_dict(self.nodes[1].getnetworkinfo())
- for net in ['ipv4','ipv6']:
+ assert_equal(NETWORKS, n1.keys())
+ for net in ['ipv4', 'ipv6']:
assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr))
assert_equal(n1[net]['proxy_randomize_credentials'], False)
assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
@@ -185,17 +213,20 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(n1['onion']['reachable'], True)
n2 = networks_dict(self.nodes[2].getnetworkinfo())
- for net in ['ipv4','ipv6','onion']:
+ assert_equal(NETWORKS, n2.keys())
+ for net in NETWORKS:
assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr))
assert_equal(n2[net]['proxy_randomize_credentials'], True)
assert_equal(n2['onion']['reachable'], True)
if self.have_ipv6:
n3 = networks_dict(self.nodes[3].getnetworkinfo())
- for net in ['ipv4','ipv6']:
+ assert_equal(NETWORKS, n3.keys())
+ for net in NETWORKS:
assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
assert_equal(n3[net]['proxy_randomize_credentials'], False)
assert_equal(n3['onion']['reachable'], False)
+
if __name__ == '__main__':
ProxyTest().main()
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index e370e11a3e..f09bffe2d4 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -18,8 +18,6 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_raises_rpc_error,
- connect_nodes,
- disconnect_nodes,
)
# Rescans start at the earliest block up to 2 hours before a key timestamp, so
@@ -102,11 +100,11 @@ class PruneTest(BitcoinTestFramework):
self.prunedir = os.path.join(self.nodes[2].datadir, self.chain, 'blocks', '')
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 2)
- connect_nodes(self.nodes[0], 2)
- connect_nodes(self.nodes[0], 3)
- connect_nodes(self.nodes[0], 4)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 2)
+ self.connect_nodes(0, 2)
+ self.connect_nodes(0, 3)
+ self.connect_nodes(0, 4)
self.sync_blocks(self.nodes[0:5])
def setup_nodes(self):
@@ -148,8 +146,8 @@ class PruneTest(BitcoinTestFramework):
for _ in range(12):
# Disconnect node 0 so it can mine a longer reorg chain without knowing about node 1's soon-to-be-stale chain
# Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects
- disconnect_nodes(self.nodes[0], 1)
- disconnect_nodes(self.nodes[0], 2)
+ self.disconnect_nodes(0, 1)
+ self.disconnect_nodes(0, 2)
# Mine 24 blocks in node 1
mine_large_blocks(self.nodes[1], 24)
@@ -157,8 +155,8 @@ class PruneTest(BitcoinTestFramework):
mine_large_blocks(self.nodes[0], 25)
# Create connections in the order so both nodes can see the reorg at the same time
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(0, 2)
self.sync_blocks(self.nodes[0:3])
self.log.info("Usage can be over target because of high stale rate: %d" % calc_usage(self.prunedir))
@@ -187,15 +185,15 @@ class PruneTest(BitcoinTestFramework):
self.log.info("New best height: %d" % self.nodes[1].getblockcount())
# Disconnect node1 and generate the new chain
- disconnect_nodes(self.nodes[0], 1)
- disconnect_nodes(self.nodes[1], 2)
+ self.disconnect_nodes(0, 1)
+ self.disconnect_nodes(1, 2)
self.log.info("Generating new longer chain of 300 more blocks")
self.nodes[1].generate(300)
self.log.info("Reconnect nodes")
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 2)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 2)
self.sync_blocks(self.nodes[0:3], timeout=120)
self.log.info("Verify height on node 2: %d" % self.nodes[2].getblockcount())
@@ -336,7 +334,7 @@ class PruneTest(BitcoinTestFramework):
# check that wallet loads successfully when restarting a pruned node after IBD.
# this was reported to fail in #7494.
self.log.info("Syncing node 5 to test wallet")
- connect_nodes(self.nodes[0], 5)
+ self.connect_nodes(0, 5)
nds = [self.nodes[0], self.nodes[5]]
self.sync_blocks(nds, wait=5, timeout=300)
self.restart_node(5, extra_args=["-prune=550"]) # restart to trigger rescan
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index 0842972779..7bd2fc7847 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -22,7 +22,6 @@ from test_framework.util import (
assert_equal,
assert_is_hex_string,
assert_raises_rpc_error,
- connect_nodes,
hex_str_to_bytes,
try_rpc,
)
@@ -61,14 +60,12 @@ class SegWitTest(BitcoinTestFramework):
],
[
"-acceptnonstdtxn=1",
- "-blockversion=4",
"-rpcserialversion=1",
"-segwitheight=432",
"-addresstype=legacy",
],
[
"-acceptnonstdtxn=1",
- "-blockversion=536870915",
"-segwitheight=432",
"-addresstype=legacy",
],
@@ -80,7 +77,7 @@ class SegWitTest(BitcoinTestFramework):
def setup_network(self):
super().setup_network()
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 2)
self.sync_all()
def success_mine(self, node, txid, sign, redeem_script=""):
diff --git a/test/functional/feature_settings.py b/test/functional/feature_settings.py
index 3705caf4ff..5a0236401d 100755
--- a/test/functional/feature_settings.py
+++ b/test/functional/feature_settings.py
@@ -31,19 +31,25 @@ class SettingsTest(BitcoinTestFramework):
# Assert settings are parsed and logged
with settings.open("w") as fp:
- json.dump({"string": "string", "num": 5, "bool": True, "null": None, "list": [6,7]}, fp)
+ json.dump({"string": "string", "num": 5, "bool": True, "null": None, "list": [6, 7]}, fp)
with node.assert_debug_log(expected_msgs=[
+ 'Ignoring unknown rw_settings value bool',
+ 'Ignoring unknown rw_settings value list',
+ 'Ignoring unknown rw_settings value null',
+ 'Ignoring unknown rw_settings value num',
+ 'Ignoring unknown rw_settings value string',
'Setting file arg: string = "string"',
'Setting file arg: num = 5',
'Setting file arg: bool = true',
'Setting file arg: null = null',
- 'Setting file arg: list = [6,7]']):
+ 'Setting file arg: list = [6,7]',
+ ]):
self.start_node(0)
self.stop_node(0)
# Assert settings are unchanged after shutdown
with settings.open() as fp:
- assert_equal(json.load(fp), {"string": "string", "num": 5, "bool": True, "null": None, "list": [6,7]})
+ assert_equal(json.load(fp), {"string": "string", "num": 5, "bool": True, "null": None, "list": [6, 7]})
# Test invalid json
with settings.open("w") as fp:
diff --git a/test/functional/feature_taproot.py b/test/functional/feature_taproot.py
index 7b534c1c2f..6ee2b72c11 100755
--- a/test/functional/feature_taproot.py
+++ b/test/functional/feature_taproot.py
@@ -9,6 +9,7 @@ from test_framework.blocktools import (
create_block,
add_witness_commitment,
MAX_BLOCK_SIGOPS_WEIGHT,
+ NORMAL_GBT_REQUEST_PARAMS,
WITNESS_SCALE_FACTOR,
)
from test_framework.messages import (
@@ -443,6 +444,8 @@ def make_spender(comment, *, tap=None, witv0=False, script=None, pkh=None, p2sh=
* standard: whether the (valid version of) spending is expected to be standard
* err_msg: a string with an expected error message for failure (or None, if not cared about)
* sigops_weight: the pre-taproot sigops weight consumed by a successful spend
+ * need_vin_vout_mismatch: whether this test requires being tested in a transaction input that has no corresponding
+ transaction output.
"""
conf = dict()
@@ -1129,13 +1132,13 @@ def spenders_taproot_inactive():
]
tap = taproot_construct(pub, scripts)
- # Test that keypath spending is valid & standard if compliant, but valid and nonstandard otherwise.
- add_spender(spenders, "inactive/keypath_valid", key=sec, tap=tap)
+ # Test that keypath spending is valid & non-standard, regardless of validity.
+ add_spender(spenders, "inactive/keypath_valid", key=sec, tap=tap, standard=False)
add_spender(spenders, "inactive/keypath_invalidsig", key=sec, tap=tap, standard=False, sighash=bitflipper(default_sighash))
add_spender(spenders, "inactive/keypath_empty", key=sec, tap=tap, standard=False, witness=[])
- # Same for scriptpath spending (but using future features like annex, leaf versions, or OP_SUCCESS is nonstandard).
- add_spender(spenders, "inactive/scriptpath_valid", key=sec, tap=tap, leaf="pk", inputs=[getter("sign")])
+ # Same for scriptpath spending (and features like annex, leaf versions, or OP_SUCCESS don't change this)
+ add_spender(spenders, "inactive/scriptpath_valid", key=sec, tap=tap, leaf="pk", standard=False, inputs=[getter("sign")])
add_spender(spenders, "inactive/scriptpath_invalidsig", key=sec, tap=tap, leaf="pk", standard=False, inputs=[getter("sign")], sighash=bitflipper(default_sighash))
add_spender(spenders, "inactive/scriptpath_invalidcb", key=sec, tap=tap, leaf="pk", standard=False, inputs=[getter("sign")], controlblock=bitflipper(default_controlblock))
add_spender(spenders, "inactive/scriptpath_valid_unkleaf", key=sec, tap=tap, leaf="future_leaf", standard=False, inputs=[getter("sign")])
@@ -1199,7 +1202,7 @@ class TaprootTest(BitcoinTestFramework):
self.num_nodes = 2
self.setup_clean_chain = True
# Node 0 has Taproot inactive, Node 1 active.
- self.extra_args = [["-whitelist=127.0.0.1", "-par=1", "-vbparams=taproot:1:1"], ["-whitelist=127.0.0.1", "-par=1"]]
+ self.extra_args = [["-par=1", "-vbparams=taproot:1:1"], ["-par=1"]]
def block_submit(self, node, txs, msg, err_msg, cb_pubkey=None, fees=0, sigops_weight=0, witness=False, accept=False):
@@ -1218,7 +1221,7 @@ class TaprootTest(BitcoinTestFramework):
witness and add_witness_commitment(block)
block.rehash()
block.solve()
- block_response = node.submitblock(block.serialize(True).hex())
+ block_response = node.submitblock(block.serialize().hex())
if err_msg is not None:
assert block_response is not None and err_msg in block_response, "Missing error message '%s' from block response '%s': %s" % (err_msg, "(None)" if block_response is None else block_response, msg)
if (accept):
@@ -1436,22 +1439,46 @@ class TaprootTest(BitcoinTestFramework):
self.log.info(" - Done")
def run_test(self):
- self.connect_nodes(0, 1)
-
# Post-taproot activation tests go first (pre-taproot tests' blocks are invalid post-taproot).
self.log.info("Post-activation tests...")
self.nodes[1].generate(101)
self.test_spenders(self.nodes[1], spenders_taproot_active(), input_counts=[1, 2, 2, 2, 2, 3])
- # Transfer % of funds to pre-taproot node.
+ # Re-connect nodes in case they have been disconnected
+ self.disconnect_nodes(0, 1)
+ self.connect_nodes(0, 1)
+
+ # Transfer value of the largest 500 coins to pre-taproot node.
addr = self.nodes[0].getnewaddress()
- self.nodes[1].sendtoaddress(address=addr, amount=int(self.nodes[1].getbalance() * 70000000) / 100000000)
- self.nodes[1].generate(1)
+
+ unsp = self.nodes[1].listunspent()
+ unsp = sorted(unsp, key=lambda i: i['amount'], reverse=True)
+ unsp = unsp[:500]
+
+ rawtx = self.nodes[1].createrawtransaction(
+ inputs=[{
+ 'txid': i['txid'],
+ 'vout': i['vout']
+ } for i in unsp],
+ outputs={addr: sum(i['amount'] for i in unsp)}
+ )
+ rawtx = self.nodes[1].signrawtransactionwithwallet(rawtx)['hex']
+
+ # Mine a block with the transaction
+ block = create_block(tmpl=self.nodes[1].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS), txlist=[rawtx])
+ add_witness_commitment(block)
+ block.rehash()
+ block.solve()
+ assert_equal(None, self.nodes[1].submitblock(block.serialize().hex()))
self.sync_blocks()
# Pre-taproot activation tests.
self.log.info("Pre-activation tests...")
- self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[1, 2, 2, 2, 2, 3])
+ # Run each test twice; once in isolation, and once combined with others. Testing in isolation
+ # means that the standardness is verified in every test (as combined transactions are only standard
+ # when all their inputs are standard).
+ self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[1])
+ self.test_spenders(self.nodes[0], spenders_taproot_inactive(), input_counts=[2, 3])
if __name__ == '__main__':
diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py
index a0bc937f75..d675ae174c 100755
--- a/test/functional/interface_zmq.py
+++ b/test/functional/interface_zmq.py
@@ -11,7 +11,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import CTransaction, hash256, FromHex
from test_framework.util import (
assert_equal,
- connect_nodes,
assert_raises_rpc_error,
)
from io import BytesIO
@@ -102,7 +101,7 @@ class ZMQTest (BitcoinTestFramework):
rawtx = subs[3]
self.restart_node(0, ["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [hashblock, hashtx, rawblock, rawtx]])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
for socket in sockets:
socket.connect(address)
@@ -207,7 +206,7 @@ class ZMQTest (BitcoinTestFramework):
connect_blocks = self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_P2WSH_OP_TRUE)
# nodes[0] will reorg chain after connecting back nodes[1]
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks() # tx in mempool valid but not advertised
# Should receive nodes[1] tip
@@ -264,7 +263,7 @@ class ZMQTest (BitcoinTestFramework):
self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_P2WSH_OP_TRUE)
# nodes[0] will reorg chain after connecting back nodes[1]
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
# Then we receive all block (dis)connect notifications for the 2 block reorg
assert_equal((dc_block, "D", None), seq.receive_sequence())
@@ -406,7 +405,7 @@ class ZMQTest (BitcoinTestFramework):
seq = ZMQSubscriber(socket, b'sequence')
self.restart_node(0, ['-zmqpub%s=%s' % (seq.topic.decode(), address)])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
socket.connect(address)
# Relax so that the subscriber is ready before publishing zmq messages
sleep(0.2)
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index 57a059b7f7..fc4c775668 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -83,31 +83,31 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
)
self.log.info('A transaction not in the mempool')
- fee = 0.00000700
+ fee = Decimal('0.000007')
raw_tx_0 = node.signrawtransactionwithwallet(node.createrawtransaction(
inputs=[{"txid": txid_in_block, "vout": 0, "sequence": BIP125_SEQUENCE_NUMBER}], # RBF is used later
- outputs=[{node.getnewaddress(): 0.3 - fee}],
+ outputs=[{node.getnewaddress(): Decimal('0.3') - fee}],
))['hex']
tx = CTransaction()
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_0)))
txid_0 = tx.rehash()
self.check_mempool_result(
- result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': Decimal(str(fee))}}],
+ result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee}}],
rawtxs=[raw_tx_0],
)
self.log.info('A final transaction not in the mempool')
coin = coins.pop() # Pick a random coin(base) to spend
- output_amount = 0.025
+ output_amount = Decimal('0.025')
raw_tx_final = node.signrawtransactionwithwallet(node.createrawtransaction(
inputs=[{'txid': coin['txid'], 'vout': coin['vout'], "sequence": 0xffffffff}], # SEQUENCE_FINAL
outputs=[{node.getnewaddress(): output_amount}],
locktime=node.getblockcount() + 2000, # Can be anything
))['hex']
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_final)))
- fee_expected = int(coin['amount']) - output_amount
+ fee_expected = coin['amount'] - output_amount
self.check_mempool_result(
- result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': Decimal(str(fee_expected))}}],
+ result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': fee_expected}}],
rawtxs=[tx.serialize().hex()],
maxfeerate=0,
)
@@ -130,7 +130,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_0)))
txid_0 = tx.rehash()
self.check_mempool_result(
- result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': Decimal(str(2 * fee))}}],
+ result_expected=[{'txid': txid_0, 'allowed': True, 'vsize': tx.get_vsize(), 'fees': {'base': (2 * fee)}}],
rawtxs=[raw_tx_0],
)
@@ -190,7 +190,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx_reference)))
# Reference tx should be valid on itself
self.check_mempool_result(
- result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal(str(0.1 - 0.05))}}],
+ result_expected=[{'txid': tx.rehash(), 'allowed': True, 'vsize': tx.get_vsize(), 'fees': { 'base': Decimal('0.1') - Decimal('0.05')}}],
rawtxs=[tx.serialize().hex()],
maxfeerate=0,
)
diff --git a/test/functional/mempool_compatibility.py b/test/functional/mempool_compatibility.py
index 7168cb4ab2..8ac91bd008 100755
--- a/test/functional/mempool_compatibility.py
+++ b/test/functional/mempool_compatibility.py
@@ -29,7 +29,7 @@ class MempoolCompatibilityTest(BitcoinTestFramework):
def setup_network(self):
self.add_nodes(self.num_nodes, versions=[
- 150200, # oldest version supported by the test framework
+ 190100, # oldest version with getmempoolinfo.loaded (used to avoid intermittent issues)
None,
])
self.start_nodes()
@@ -72,5 +72,6 @@ class MempoolCompatibilityTest(BitcoinTestFramework):
assert old_tx_hash in old_node.getrawmempool()
assert unbroadcasted_tx_hash in old_node.getrawmempool()
+
if __name__ == "__main__":
MempoolCompatibilityTest().main()
diff --git a/test/functional/mempool_expiry.py b/test/functional/mempool_expiry.py
index 8b9b7b155a..4c46075ae9 100755
--- a/test/functional/mempool_expiry.py
+++ b/test/functional/mempool_expiry.py
@@ -16,8 +16,8 @@ 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 import MiniWallet
DEFAULT_MEMPOOL_EXPIRY = 336 # hours
CUSTOM_MEMPOOL_EXPIRY = 10 # hours
@@ -26,44 +26,50 @@ CUSTOM_MEMPOOL_EXPIRY = 10 # hours
class MempoolExpiryTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
-
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
+ self.setup_clean_chain = True
def test_transaction_expiry(self, timeout):
"""Tests that a transaction expires after the expiry timeout and its
children are removed as well."""
node = self.nodes[0]
+ self.wallet = MiniWallet(node)
+
+ # Add enough mature utxos to the wallet so that all txs spend confirmed coins.
+ self.wallet.generate(4)
+ node.generate(100)
# Send a parent transaction that will expire.
- parent_address = node.getnewaddress()
- parent_txid = node.sendtoaddress(parent_address, 1.0)
+ parent_txid = self.wallet.send_self_transfer(from_node=node)['txid']
+ parent_utxo = self.wallet.get_utxo(txid=parent_txid)
+ independent_utxo = self.wallet.get_utxo()
+
+ # Ensure the transactions we send to trigger the mempool check spend utxos that are independent of
+ # the transactions being tested for expiration.
+ trigger_utxo1 = self.wallet.get_utxo()
+ trigger_utxo2 = self.wallet.get_utxo()
# Set the mocktime to the arrival time of the parent transaction.
entry_time = node.getmempoolentry(parent_txid)['time']
node.setmocktime(entry_time)
- # Create child transaction spending the parent transaction
- vout = find_vout_for_address(node, parent_txid, parent_address)
- inputs = [{'txid': parent_txid, 'vout': vout}]
- outputs = {node.getnewaddress(): 0.99}
- child_raw = node.createrawtransaction(inputs, outputs)
- child_signed = node.signrawtransactionwithwallet(child_raw)['hex']
-
- # Let half of the timeout elapse and broadcast the child transaction.
+ # Let half of the timeout elapse and broadcast the child transaction spending the parent transaction.
half_expiry_time = entry_time + int(60 * 60 * timeout/2)
node.setmocktime(half_expiry_time)
- child_txid = node.sendrawtransaction(child_signed)
+ child_txid = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=parent_utxo)['txid']
+ assert_equal(parent_txid, node.getmempoolentry(child_txid)['depends'][0])
self.log.info('Broadcast child transaction after {} hours.'.format(
timedelta(seconds=(half_expiry_time-entry_time))))
+ # Broadcast another (independent) transaction.
+ independent_txid = self.wallet.send_self_transfer(from_node=node, utxo_to_spend=independent_utxo)['txid']
+
# Let most of the timeout elapse and check that the parent tx is still
# in the mempool.
nearly_expiry_time = entry_time + 60 * 60 * timeout - 5
node.setmocktime(nearly_expiry_time)
- # Expiry of mempool transactions is only checked when a new transaction
- # is added to the to the mempool.
- node.sendtoaddress(node.getnewaddress(), 1.0)
+ # Broadcast a transaction as the expiry of transactions in the mempool is only checked
+ # when a new transaction is added to the mempool.
+ self.wallet.send_self_transfer(from_node=node, utxo_to_spend=trigger_utxo1)
self.log.info('Test parent tx not expired after {} hours.'.format(
timedelta(seconds=(nearly_expiry_time-entry_time))))
assert_equal(entry_time, node.getmempoolentry(parent_txid)['time'])
@@ -72,9 +78,8 @@ class MempoolExpiryTest(BitcoinTestFramework):
# has passed.
expiry_time = entry_time + 60 * 60 * timeout + 5
node.setmocktime(expiry_time)
- # Expiry of mempool transactions is only checked when a new transaction
- # is added to the to the mempool.
- node.sendtoaddress(node.getnewaddress(), 1.0)
+ # Again, broadcast a transaction so the expiry of transactions in the mempool is checked.
+ self.wallet.send_self_transfer(from_node=node, utxo_to_spend=trigger_utxo2)
self.log.info('Test parent tx expiry after {} hours.'.format(
timedelta(seconds=(expiry_time-entry_time))))
assert_raises_rpc_error(-5, 'Transaction not in mempool',
@@ -85,6 +90,11 @@ class MempoolExpiryTest(BitcoinTestFramework):
assert_raises_rpc_error(-5, 'Transaction not in mempool',
node.getmempoolentry, child_txid)
+ # Check that the independent tx is still in the mempool.
+ self.log.info('Test the independent tx not expired after {} hours.'.format(
+ timedelta(seconds=(expiry_time-half_expiry_time))))
+ assert_equal(half_expiry_time, node.getmempoolentry(independent_txid)['time'])
+
def run_test(self):
self.log.info('Test default mempool expiry timeout of %d hours.' %
DEFAULT_MEMPOOL_EXPIRY)
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
index f73f1a02a2..70cd4ebb3b 100755
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -45,8 +45,6 @@ from test_framework.util import (
assert_equal,
assert_greater_than_or_equal,
assert_raises_rpc_error,
- connect_nodes,
- disconnect_nodes,
)
@@ -83,11 +81,11 @@ class MempoolPersistTest(BitcoinTestFramework):
assert_greater_than_or_equal(tx_creation_time_higher, tx_creation_time)
# disconnect nodes & make a txn that remains in the unbroadcast set.
- disconnect_nodes(self.nodes[0], 1)
+ self.disconnect_nodes(0, 1)
assert(len(self.nodes[0].getpeerinfo()) == 0)
assert(len(self.nodes[0].p2ps) == 0)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("12"))
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 2)
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()
diff --git a/test/functional/mempool_spend_coinbase.py b/test/functional/mempool_spend_coinbase.py
index 854d506f0d..86d382ff69 100755
--- a/test/functional/mempool_spend_coinbase.py
+++ b/test/functional/mempool_spend_coinbase.py
@@ -13,44 +13,48 @@ but less mature coinbase spends are NOT.
"""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.blocktools import create_raw_transaction
from test_framework.util import assert_equal, assert_raises_rpc_error
+from test_framework.wallet import MiniWallet
class MempoolSpendCoinbaseTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
-
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
+ self.setup_clean_chain = True
def run_test(self):
+ wallet = MiniWallet(self.nodes[0])
+
+ wallet.generate(200)
chain_height = self.nodes[0].getblockcount()
assert_equal(chain_height, 200)
- node0_address = self.nodes[0].getnewaddress()
# Coinbase at height chain_height-100+1 ok in mempool, should
# get mined. Coinbase at height chain_height-100+2 is
- # is too immature to spend.
+ # too immature to spend.
b = [self.nodes[0].getblockhash(n) for n in range(101, 103)]
coinbase_txids = [self.nodes[0].getblock(h)['tx'][0] for h in b]
- spends_raw = [create_raw_transaction(self.nodes[0], txid, node0_address, amount=49.99) for txid in coinbase_txids]
+ utxo_101 = wallet.get_utxo(txid=coinbase_txids[0])
+ utxo_102 = wallet.get_utxo(txid=coinbase_txids[1])
- spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
+ spend_101_id = wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_101)["txid"]
# coinbase at height 102 should be too immature to spend
- assert_raises_rpc_error(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1])
+ assert_raises_rpc_error(-26,
+ "bad-txns-premature-spend-of-coinbase",
+ lambda: wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_102))
# mempool should have just spend_101:
- assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ])
+ assert_equal(self.nodes[0].getrawmempool(), [spend_101_id])
# mine a block, spend_101 should get confirmed
self.nodes[0].generate(1)
assert_equal(set(self.nodes[0].getrawmempool()), set())
# ... and now height 102 can be spent:
- spend_102_id = self.nodes[0].sendrawtransaction(spends_raw[1])
- assert_equal(self.nodes[0].getrawmempool(), [ spend_102_id ])
+ spend_102_id = wallet.send_self_transfer(from_node=self.nodes[0], utxo_to_spend=utxo_102)["txid"]
+ assert_equal(self.nodes[0].getrawmempool(), [spend_102_id])
+
if __name__ == '__main__':
MempoolSpendCoinbaseTest().main()
diff --git a/test/functional/mempool_unbroadcast.py b/test/functional/mempool_unbroadcast.py
index abd5a03d95..b475b65e68 100755
--- a/test/functional/mempool_unbroadcast.py
+++ b/test/functional/mempool_unbroadcast.py
@@ -11,9 +11,7 @@ from test_framework.p2p import P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
create_confirmed_utxos,
- disconnect_nodes,
)
MAX_INITIAL_BROADCAST_DELAY = 15 * 60 # 15 minutes in seconds
@@ -36,7 +34,7 @@ class MempoolUnbroadcastTest(BitcoinTestFramework):
min_relay_fee = node.getnetworkinfo()["relayfee"]
utxos = create_confirmed_utxos(min_relay_fee, node, 10)
- disconnect_nodes(node, 1)
+ self.disconnect_nodes(0, 1)
self.log.info("Generate transactions that only node 0 knows about")
@@ -70,7 +68,7 @@ class MempoolUnbroadcastTest(BitcoinTestFramework):
self.restart_node(0)
self.log.info("Reconnect nodes & check if they are sent to node 1")
- connect_nodes(node, 1)
+ self.connect_nodes(0, 1)
# fast forward into the future & ensure that the second node has the txns
node.mockscheduler(MAX_INITIAL_BROADCAST_DELAY)
@@ -91,7 +89,7 @@ class MempoolUnbroadcastTest(BitcoinTestFramework):
time.sleep(2) # allow sufficient time for possibility of broadcast
assert_equal(len(conn.get_invs()), 0)
- disconnect_nodes(node, 1)
+ self.disconnect_nodes(0, 1)
node.disconnect_p2ps()
def test_txn_removal(self):
diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py
index 1b2c7644bd..ba467c1517 100755
--- a/test/functional/mining_basic.py
+++ b/test/functional/mining_basic.py
@@ -13,6 +13,7 @@ from decimal import Decimal
from test_framework.blocktools import (
create_coinbase,
+ NORMAL_GBT_REQUEST_PARAMS,
TIME_GENESIS_BLOCK,
)
from test_framework.messages import (
@@ -25,9 +26,11 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
)
+VERSIONBITS_TOP_BITS = 0x20000000
+VERSIONBITS_DEPLOYMENT_TESTDUMMY_BIT = 28
+
def assert_template(node, block, expect, rehash=True):
if rehash:
@@ -55,8 +58,16 @@ class MiningTest(BitcoinTestFramework):
assert_equal(mining_info['blocks'], 200)
assert_equal(mining_info['currentblocktx'], 0)
assert_equal(mining_info['currentblockweight'], 4000)
+
+ self.log.info('test blockversion')
+ self.restart_node(0, extra_args=['-mocktime={}'.format(t), '-blockversion=1337'])
+ self.connect_nodes(0, 1)
+ assert_equal(1337, self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)['version'])
+ self.restart_node(0, extra_args=['-mocktime={}'.format(t)])
+ self.connect_nodes(0, 1)
+ assert_equal(VERSIONBITS_TOP_BITS + (1 << VERSIONBITS_DEPLOYMENT_TESTDUMMY_BIT), self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)['version'])
self.restart_node(0)
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
def run_test(self):
self.mine_chain()
@@ -80,7 +91,7 @@ class MiningTest(BitcoinTestFramework):
# Mine a block to leave initial block download
node.generatetoaddress(1, node.get_deterministic_priv_key().address)
- tmpl = node.getblocktemplate({'rules': ['segwit']})
+ tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
self.log.info("getblocktemplate: Test capability advertised")
assert 'proposal' in tmpl['capabilities']
assert 'coinbasetxn' not in tmpl
diff --git a/test/functional/mining_getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py
index 6d0b241e57..2adafb1fdb 100755
--- a/test/functional/mining_getblocktemplate_longpoll.py
+++ b/test/functional/mining_getblocktemplate_longpoll.py
@@ -5,11 +5,13 @@
"""Test longpolling with getblocktemplate."""
from decimal import Decimal
+import random
+import threading
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import get_rpc_proxy, random_transaction
+from test_framework.util import get_rpc_proxy
+from test_framework.wallet import MiniWallet
-import threading
class LongpollThread(threading.Thread):
def __init__(self, node):
@@ -29,45 +31,48 @@ class GetBlockTemplateLPTest(BitcoinTestFramework):
self.num_nodes = 2
self.supports_cli = False
- def skip_test_if_missing_module(self):
- self.skip_if_no_wallet()
-
def run_test(self):
self.log.info("Warning: this test will take about 70 seconds in the best case. Be patient.")
+ self.log.info("Test that longpollid doesn't change between successive getblocktemplate() invocations if nothing else happens")
self.nodes[0].generate(10)
template = self.nodes[0].getblocktemplate({'rules': ['segwit']})
longpollid = template['longpollid']
- # longpollid should not change between successive invocations if nothing else happens
template2 = self.nodes[0].getblocktemplate({'rules': ['segwit']})
assert template2['longpollid'] == longpollid
- # Test 1: test that the longpolling wait if we do nothing
+ self.log.info("Test that longpoll waits if we do nothing")
thr = LongpollThread(self.nodes[0])
thr.start()
# check that thread still lives
thr.join(5) # wait 5 seconds or until thread exits
assert thr.is_alive()
- # Test 2: test that longpoll will terminate if another node generates a block
- self.nodes[1].generate(1) # generate a block on another node
+ miniwallets = [ MiniWallet(node) for node in self.nodes ]
+ self.log.info("Test that longpoll will terminate if another node generates a block")
+ miniwallets[1].generate(1) # generate a block on another node
# check that thread will exit now that new transaction entered mempool
thr.join(5) # wait 5 seconds or until thread exits
assert not thr.is_alive()
- # Test 3: test that longpoll will terminate if we generate a block ourselves
+ self.log.info("Test that longpoll will terminate if we generate a block ourselves")
thr = LongpollThread(self.nodes[0])
thr.start()
- self.nodes[0].generate(1) # generate a block on another node
+ miniwallets[0].generate(1) # generate a block on own node
thr.join(5) # wait 5 seconds or until thread exits
assert not thr.is_alive()
- # Test 4: test that introducing a new transaction into the mempool will terminate the longpoll
+ # Add enough mature utxos to the wallets, so that all txs spend confirmed coins
+ self.nodes[0].generate(100)
+ self.sync_blocks()
+
+ self.log.info("Test that introducing a new transaction into the mempool will terminate the longpoll")
thr = LongpollThread(self.nodes[0])
thr.start()
# generate a random transaction and submit it
min_relay_fee = self.nodes[0].getnetworkinfo()["relayfee"]
- # min_relay_fee is fee per 1000 bytes, which should be more than enough.
- (txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"), min_relay_fee, Decimal("0.001"), 20)
+ fee_rate = min_relay_fee + Decimal('0.00000010') * random.randint(0,20)
+ miniwallets[0].send_self_transfer(from_node=random.choice(self.nodes),
+ fee_rate=fee_rate)
# after one minute, every 10 seconds the mempool is probed, so in 80 seconds it should have returned
thr.join(60 + 20)
assert not thr.is_alive()
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index 80f262d0d3..91fbd722cf 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -19,8 +19,11 @@ from test_framework.util import (
)
import time
+# Keep this with length <= 10. Addresses from larger messages are not relayed.
ADDRS = []
-for i in range(10):
+num_ipv4_addrs = 10
+
+for i in range(num_ipv4_addrs):
addr = CAddress()
addr.time = int(time.time()) + i
addr.nServices = NODE_NETWORK | NODE_WITNESS
@@ -30,11 +33,15 @@ for i in range(10):
class AddrReceiver(P2PInterface):
+ num_ipv4_received = 0
+
def on_addr(self, message):
for addr in message.addrs:
assert_equal(addr.nServices, 9)
+ if not 8333 <= addr.port < 8343:
+ raise AssertionError("Invalid addr.port of {} (8333-8342 expected)".format(addr.port))
assert addr.ip.startswith('123.123.123.')
- assert (8333 <= addr.port < 8343)
+ self.num_ipv4_received += 1
class AddrTest(BitcoinTestFramework):
@@ -48,21 +55,33 @@ class AddrTest(BitcoinTestFramework):
msg = msg_addr()
self.log.info('Send too-large addr message')
- msg.addrs = ADDRS * 101
+ msg.addrs = ADDRS * 101 # more than 1000 addresses in one message
with self.nodes[0].assert_debug_log(['addr message size = 1010']):
addr_source.send_and_ping(msg)
self.log.info('Check that addr message content is relayed and added to addrman')
- addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
+ num_receivers = 7
+ receivers = []
+ for _ in range(num_receivers):
+ receivers.append(self.nodes[0].add_p2p_connection(AddrReceiver()))
msg.addrs = ADDRS
- with self.nodes[0].assert_debug_log([
- 'Added 10 addresses from 127.0.0.1: 0 tried',
+ with self.nodes[0].assert_debug_log(
+ [
+ 'Added {} addresses from 127.0.0.1: 0 tried'.format(num_ipv4_addrs),
'received: addr (301 bytes) peer=0',
- 'sending addr (301 bytes) peer=1',
- ]):
+ ]
+ ):
addr_source.send_and_ping(msg)
self.nodes[0].setmocktime(int(time.time()) + 30 * 60)
- addr_receiver.sync_with_ping()
+ for receiver in receivers:
+ receiver.sync_with_ping()
+
+ total_ipv4_received = sum(r.num_ipv4_received for r in receivers)
+
+ # Every IPv4 address must be relayed to two peers, other than the
+ # originating node (addr_source).
+ ipv4_branching_factor = 2
+ assert_equal(total_ipv4_received, num_ipv4_addrs * ipv4_branching_factor)
if __name__ == '__main__':
diff --git a/test/functional/p2p_blockfilters.py b/test/functional/p2p_blockfilters.py
index 84178d0dd7..3250cbecf9 100755
--- a/test/functional/p2p_blockfilters.py
+++ b/test/functional/p2p_blockfilters.py
@@ -22,8 +22,6 @@ from test_framework.p2p import P2PInterface
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
- disconnect_nodes,
)
class CFiltersClient(P2PInterface):
@@ -61,7 +59,7 @@ class CompactFiltersTest(BitcoinTestFramework):
self.sync_blocks(timeout=600)
# Stale blocks by disconnecting nodes 0 & 1, mining, then reconnecting
- disconnect_nodes(self.nodes[0], 1)
+ self.disconnect_nodes(0, 1)
self.nodes[0].generate(1)
self.wait_until(lambda: self.nodes[0].getblockcount() == 1000)
@@ -90,7 +88,7 @@ class CompactFiltersTest(BitcoinTestFramework):
assert_equal(len(response.headers), 1)
self.log.info("Reorg node 0 to a new chain.")
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks(timeout=600)
main_block_hash = self.nodes[0].getblockhash(1000)
diff --git a/test/functional/p2p_blocksonly.py b/test/functional/p2p_blocksonly.py
index 646baa1550..e80422d1cf 100755
--- a/test/functional/p2p_blocksonly.py
+++ b/test/functional/p2p_blocksonly.py
@@ -59,7 +59,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
self.log.info('Check that txs from peers with relay-permission are not rejected and relayed to others')
self.log.info("Restarting node 0 with relay permission and blocksonly")
- self.restart_node(0, ["-persistmempool=0", "-whitelist=relay@127.0.0.1", "-blocksonly"])
+ self.restart_node(0, ["-persistmempool=0", "-whitelist=relay@127.0.0.1", "-blocksonly", '-deprecatedrpc=whitelisted'])
assert_equal(self.nodes[0].getrawmempool(), [])
first_peer = self.nodes[0].add_p2p_connection(P2PInterface())
second_peer = self.nodes[0].add_p2p_connection(P2PInterface())
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 506b480039..9a9df73049 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -9,7 +9,7 @@ Version 2 compact blocks are post-segwit (wtxids)
"""
import random
-from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment
+from test_framework.blocktools import create_block, NORMAL_GBT_REQUEST_PARAMS, add_witness_commitment
from test_framework.messages import BlockTransactions, BlockTransactionsRequest, calculate_shortid, CBlock, CBlockHeader, CInv, COutPoint, CTransaction, CTxIn, CTxInWitness, CTxOut, FromHex, HeaderAndShortIDs, msg_no_witness_block, msg_no_witness_blocktxn, msg_cmpctblock, msg_getblocktxn, msg_getdata, msg_getheaders, msg_headers, msg_inv, msg_sendcmpct, msg_sendheaders, msg_tx, msg_block, msg_blocktxn, MSG_BLOCK, MSG_CMPCT_BLOCK, MSG_WITNESS_FLAG, NODE_NETWORK, P2PHeaderAndShortIDs, PrefilledTransaction, ser_uint256, ToHex
from test_framework.p2p import p2p_lock, P2PInterface
from test_framework.script import CScript, OP_TRUE, OP_DROP
@@ -104,11 +104,7 @@ class CompactBlocksTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def build_block_on_tip(self, node, segwit=False):
- height = node.getblockcount()
- tip = node.getbestblockhash()
- mtp = node.getblockheader(tip)['mediantime']
- block = create_block(int(tip, 16), create_coinbase(height + 1), mtp + 1)
- block.nVersion = 4
+ block = create_block(tmpl=node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS))
if segwit:
add_witness_commitment(block)
block.solve()
@@ -768,7 +764,38 @@ class CompactBlocksTest(BitcoinTestFramework):
stalling_peer.send_and_ping(msg)
assert_equal(int(node.getbestblockhash(), 16), block.sha256)
+ def test_highbandwidth_mode_states_via_getpeerinfo(self):
+ # create new p2p connection for a fresh state w/o any prior sendcmpct messages sent
+ hb_test_node = self.nodes[0].add_p2p_connection(TestP2PConn(cmpct_version=2))
+
+ # assert the RPC getpeerinfo boolean fields `bip152_hb_{to, from}`
+ # match the given parameters for the last peer of a given node
+ def assert_highbandwidth_states(node, hb_to, hb_from):
+ peerinfo = node.getpeerinfo()[-1]
+ assert_equal(peerinfo['bip152_hb_to'], hb_to)
+ assert_equal(peerinfo['bip152_hb_from'], hb_from)
+
+ # initially, neither node has selected the other peer as high-bandwidth yet
+ assert_highbandwidth_states(self.nodes[0], hb_to=False, hb_from=False)
+
+ # peer requests high-bandwidth mode by sending sendcmpct(1)
+ hb_test_node.send_and_ping(msg_sendcmpct(announce=True, version=2))
+ assert_highbandwidth_states(self.nodes[0], hb_to=False, hb_from=True)
+
+ # peer generates a block and sends it to node, which should
+ # select the peer as high-bandwidth (up to 3 peers according to BIP 152)
+ block = self.build_block_on_tip(self.nodes[0])
+ hb_test_node.send_and_ping(msg_block(block))
+ assert_highbandwidth_states(self.nodes[0], hb_to=True, hb_from=True)
+
+ # peer requests low-bandwidth mode by sending sendcmpct(0)
+ hb_test_node.send_and_ping(msg_sendcmpct(announce=False, version=2))
+ assert_highbandwidth_states(self.nodes[0], hb_to=True, hb_from=False)
+
def run_test(self):
+ # Get the nodes out of IBD
+ self.nodes[0].generate(1)
+
# Setup the p2p connections
self.segwit_node = self.nodes[0].add_p2p_connection(TestP2PConn(cmpct_version=2))
self.old_node = self.nodes[0].add_p2p_connection(TestP2PConn(cmpct_version=1), services=NODE_NETWORK)
@@ -823,6 +850,9 @@ class CompactBlocksTest(BitcoinTestFramework):
self.log.info("Testing invalid index in cmpctblock message...")
self.test_invalid_cmpctblock_message()
+ self.log.info("Testing high-bandwidth mode states via getpeerinfo...")
+ self.test_highbandwidth_mode_states_via_getpeerinfo()
+
if __name__ == '__main__':
CompactBlocksTest().main()
diff --git a/test/functional/p2p_disconnect_ban.py b/test/functional/p2p_disconnect_ban.py
index b7c2a306eb..a7f51b5364 100755
--- a/test/functional/p2p_disconnect_ban.py
+++ b/test/functional/p2p_disconnect_ban.py
@@ -9,7 +9,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
)
class DisconnectBanTest(BitcoinTestFramework):
@@ -19,8 +18,11 @@ class DisconnectBanTest(BitcoinTestFramework):
def run_test(self):
self.log.info("Connect nodes both way")
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 0)
+ # By default, the test framework sets up an addnode connection from
+ # node 1 --> node0. By connecting node0 --> node 1, we're left with
+ # the two nodes being connected both ways.
+ # Topology will look like: node0 <--> node1
+ self.connect_nodes(0, 1)
self.log.info("Test setban and listbanned RPCs")
@@ -78,8 +80,8 @@ class DisconnectBanTest(BitcoinTestFramework):
# Clear ban lists
self.nodes[1].clearbanned()
self.log.info("Connect nodes both way")
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 0)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 0)
self.log.info("Test disconnectnode RPCs")
@@ -98,7 +100,7 @@ class DisconnectBanTest(BitcoinTestFramework):
assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
self.log.info("disconnectnode: successfully reconnect node")
- connect_nodes(self.nodes[0], 1) # reconnect the node
+ self.connect_nodes(0, 1) # reconnect the node
assert_equal(len(self.nodes[0].getpeerinfo()), 2)
assert [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1]
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index ea066a984d..51b7623fe3 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -108,9 +108,10 @@ class FeeFilterTest(BitcoinTestFramework):
# to 35 entries in an inv, which means that when this next transaction
# is eligible for relay, the prior transactions from node1 are eligible
# as well.
- txids = [miniwallet.send_self_transfer(fee_rate=Decimal('0.00020000'), from_node=node0)['wtxid'] for _ in range(3)]
+ txids = [miniwallet.send_self_transfer(fee_rate=Decimal('0.00020000'), from_node=node0)['wtxid'] for _ in range(1)]
conn.wait_for_invs_to_match(txids)
conn.clear_invs()
+ self.sync_mempools() # must be sure node 1 has received all txs
self.log.info("Remove fee filter and check txs are received again")
conn.send_and_ping(msg_feefilter(0))
diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py
index aaf862e6c8..9614ab6872 100755
--- a/test/functional/p2p_fingerprint.py
+++ b/test/functional/p2p_fingerprint.py
@@ -18,6 +18,7 @@ from test_framework.p2p import (
msg_block,
msg_getdata,
msg_getheaders,
+ p2p_lock,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -57,18 +58,6 @@ class P2PFingerprintTest(BitcoinTestFramework):
msg.hashstop = block_hash
node.send_message(msg)
- # Check whether last block received from node has a given hash
- def last_block_equals(self, expected_hash, node):
- block_msg = node.last_message.get("block")
- return block_msg and block_msg.block.rehash() == expected_hash
-
- # Check whether last block header received from node has a given hash
- def last_header_equals(self, expected_hash, node):
- headers_msg = node.last_message.get("headers")
- return (headers_msg and
- headers_msg.headers and
- headers_msg.headers[0].rehash() == expected_hash)
-
# Checks that stale blocks timestamped more than a month ago are not served
# by the node while recent stale blocks and old active chain blocks are.
# This does not currently test that stale blocks timestamped within the
@@ -101,34 +90,31 @@ class P2PFingerprintTest(BitcoinTestFramework):
# Check that getdata request for stale block succeeds
self.send_block_request(stale_hash, node0)
- test_function = lambda: self.last_block_equals(stale_hash, node0)
- self.wait_until(test_function, timeout=3)
+ node0.wait_for_block(stale_hash, timeout=3)
# Check that getheader request for stale block header succeeds
self.send_header_request(stale_hash, node0)
- test_function = lambda: self.last_header_equals(stale_hash, node0)
- self.wait_until(test_function, timeout=3)
+ node0.wait_for_header(hex(stale_hash), timeout=3)
# Longest chain is extended so stale is much older than chain tip
self.nodes[0].setmocktime(0)
- tip = self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)[0]
+ block_hash = int(self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)[-1], 16)
assert_equal(self.nodes[0].getblockcount(), 14)
-
- # Send getdata & getheaders to refresh last received getheader message
- block_hash = int(tip, 16)
- self.send_block_request(block_hash, node0)
- self.send_header_request(block_hash, node0)
- node0.sync_with_ping()
+ node0.wait_for_block(block_hash, timeout=3)
# Request for very old stale block should now fail
+ with p2p_lock:
+ node0.last_message.pop("block", None)
self.send_block_request(stale_hash, node0)
- time.sleep(3)
- assert not self.last_block_equals(stale_hash, node0)
+ node0.sync_with_ping()
+ assert "block" not in node0.last_message
# Request for very old stale block header should now fail
+ with p2p_lock:
+ node0.last_message.pop("headers", None)
self.send_header_request(stale_hash, node0)
- time.sleep(3)
- assert not self.last_header_equals(stale_hash, node0)
+ node0.sync_with_ping()
+ assert "headers" not in node0.last_message
# Verify we can fetch very old blocks and headers on the active chain
block_hash = int(block_hashes[2], 16)
@@ -137,12 +123,11 @@ class P2PFingerprintTest(BitcoinTestFramework):
node0.sync_with_ping()
self.send_block_request(block_hash, node0)
- test_function = lambda: self.last_block_equals(block_hash, node0)
- self.wait_until(test_function, timeout=3)
+ node0.wait_for_block(block_hash, timeout=3)
self.send_header_request(block_hash, node0)
- test_function = lambda: self.last_header_equals(block_hash, node0)
- self.wait_until(test_function, timeout=3)
+ node0.wait_for_header(hex(block_hash), timeout=3)
+
if __name__ == '__main__':
P2PFingerprintTest().main()
diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py
index db72a361d9..c0b3c2cb12 100755
--- a/test/functional/p2p_invalid_messages.py
+++ b/test/functional/p2p_invalid_messages.py
@@ -18,6 +18,7 @@ from test_framework.messages import (
msg_inv,
msg_ping,
MSG_TX,
+ msg_version,
ser_string,
)
from test_framework.p2p import (
@@ -60,6 +61,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
def run_test(self):
self.test_buffer()
+ self.test_duplicate_version_msg()
self.test_magic_bytes()
self.test_checksum()
self.test_size()
@@ -92,6 +94,13 @@ class InvalidMessagesTest(BitcoinTestFramework):
conn.sync_with_ping(timeout=1)
self.nodes[0].disconnect_p2ps()
+ def test_duplicate_version_msg(self):
+ self.log.info("Test duplicate version message is ignored")
+ conn = self.nodes[0].add_p2p_connection(P2PDataStore())
+ with self.nodes[0].assert_debug_log(['redundant version message from peer']):
+ conn.send_and_ping(msg_version())
+ self.nodes[0].disconnect_p2ps()
+
def test_magic_bytes(self):
self.log.info("Test message with invalid magic bytes disconnects peer")
conn = self.nodes[0].add_p2p_connection(P2PDataStore())
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index 4b32d60db0..ca8bf908a9 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -24,8 +24,6 @@ from test_framework.util import (
assert_greater_than_or_equal,
)
-DISCOURAGEMENT_THRESHOLD = 100
-
class LazyPeer(P2PInterface):
def __init__(self):
@@ -93,27 +91,16 @@ class P2PLeakTest(BitcoinTestFramework):
self.num_nodes = 1
def run_test(self):
- # Peer that never sends a version. We will send a bunch of messages
- # from this peer anyway and verify eventual disconnection.
- no_version_disconnect_peer = self.nodes[0].add_p2p_connection(
- LazyPeer(), send_version=False, wait_for_verack=False)
-
# Another peer that never sends a version, nor any other messages. It shouldn't receive anything from the node.
no_version_idle_peer = self.nodes[0].add_p2p_connection(LazyPeer(), send_version=False, wait_for_verack=False)
# Peer that sends a version but not a verack.
no_verack_idle_peer = self.nodes[0].add_p2p_connection(NoVerackIdlePeer(), wait_for_verack=False)
- # Send enough ping messages (any non-version message will do) prior to sending
- # version to reach the peer discouragement threshold. This should get us disconnected.
- for _ in range(DISCOURAGEMENT_THRESHOLD):
- no_version_disconnect_peer.send_message(msg_ping())
-
# Wait until we got the verack in response to the version. Though, don't wait for the node to receive the
# verack, since we never sent one
no_verack_idle_peer.wait_for_verack()
- no_version_disconnect_peer.wait_until(lambda: no_version_disconnect_peer.ever_connected, check_connected=False)
no_version_idle_peer.wait_until(lambda: no_version_idle_peer.ever_connected)
no_verack_idle_peer.wait_until(lambda: no_verack_idle_peer.version_received)
@@ -123,13 +110,9 @@ class P2PLeakTest(BitcoinTestFramework):
#Give the node enough time to possibly leak out a message
time.sleep(5)
- # Expect this peer to be disconnected for misbehavior
- assert not no_version_disconnect_peer.is_connected
-
self.nodes[0].disconnect_p2ps()
# Make sure no unexpected messages came in
- assert no_version_disconnect_peer.unexpected_msg == False
assert no_version_idle_peer.unexpected_msg == False
assert no_verack_idle_peer.unexpected_msg == False
@@ -148,7 +131,7 @@ class P2PLeakTest(BitcoinTestFramework):
p2p_old_peer = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)
old_version_msg = msg_version()
old_version_msg.nVersion = 31799
- with self.nodes[0].assert_debug_log(['peer=4 using obsolete version 31799; disconnecting']):
+ with self.nodes[0].assert_debug_log(['peer=3 using obsolete version 31799; disconnecting']):
p2p_old_peer.send_message(old_version_msg)
p2p_old_peer.wait_for_disconnect()
diff --git a/test/functional/p2p_node_network_limited.py b/test/functional/p2p_node_network_limited.py
index 2c9cbea5e4..b1a7ef6877 100755
--- a/test/functional/p2p_node_network_limited.py
+++ b/test/functional/p2p_node_network_limited.py
@@ -13,8 +13,6 @@ from test_framework.p2p import P2PInterface
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- disconnect_nodes,
- connect_nodes,
)
@@ -40,9 +38,9 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
self.extra_args = [['-prune=550', '-addrmantest'], [], []]
def disconnect_all(self):
- disconnect_nodes(self.nodes[0], 1)
- disconnect_nodes(self.nodes[0], 2)
- disconnect_nodes(self.nodes[1], 2)
+ self.disconnect_nodes(0, 1)
+ self.disconnect_nodes(0, 2)
+ self.disconnect_nodes(1, 2)
def setup_network(self):
self.add_nodes(self.num_nodes, self.extra_args)
@@ -60,7 +58,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16), expected_services)
self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
blocks = self.nodes[1].generatetoaddress(292, self.nodes[1].get_deterministic_priv_key().address)
self.sync_blocks([self.nodes[0], self.nodes[1]])
@@ -85,7 +83,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
# connect unsynced node 2 with pruned NODE_NETWORK_LIMITED peer
# because node 2 is in IBD and node 0 is a NODE_NETWORK_LIMITED peer, sync must not be possible
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 2)
try:
self.sync_blocks([self.nodes[0], self.nodes[2]], timeout=5)
except:
@@ -94,7 +92,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
assert_equal(self.nodes[2].getblockheader(self.nodes[2].getbestblockhash())['height'], 0)
# now connect also to node 1 (non pruned)
- connect_nodes(self.nodes[1], 2)
+ self.connect_nodes(1, 2)
# sync must be possible
self.sync_blocks()
@@ -106,7 +104,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
# connect node1 (non pruned) with node0 (pruned) and check if the can sync
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
# sync must be possible, node 1 is no longer in IBD and should therefore connect to node 0 (NODE_NETWORK_LIMITED)
self.sync_blocks([self.nodes[0], self.nodes[1]])
diff --git a/test/functional/p2p_permissions.py b/test/functional/p2p_permissions.py
index 3ec36edb41..ed82e6a2e2 100755
--- a/test/functional/p2p_permissions.py
+++ b/test/functional/p2p_permissions.py
@@ -22,7 +22,6 @@ from test_framework.test_node import ErrorMatch
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
p2p_port,
)
@@ -43,6 +42,13 @@ class P2PPermissionsTests(BitcoinTestFramework):
True)
self.checkpermission(
+ # check without deprecatedrpc=whitelisted
+ ["-whitelist=127.0.0.1"],
+ # Make sure the default values in the command line documentation match the ones here
+ ["relay", "noban", "mempool", "download"],
+ None)
+
+ self.checkpermission(
# no permission (even with forcerelay)
["-whitelist=@127.0.0.1", "-whitelistforcerelay=1"],
[],
@@ -81,6 +87,12 @@ class P2PPermissionsTests(BitcoinTestFramework):
False)
self.checkpermission(
+ # check without deprecatedrpc=whitelisted
+ ["-whitelist=noban,mempool@127.0.0.1", "-whitelistrelay"],
+ ["noban", "mempool", "download"],
+ None)
+
+ self.checkpermission(
# legacy whitelistforcerelay should be ignored
["-whitelist=noban,mempool@127.0.0.1", "-whitelistforcerelay"],
["noban", "mempool", "download"],
@@ -133,7 +145,7 @@ class P2PPermissionsTests(BitcoinTestFramework):
p2p_rebroadcast_wallet.send_txs_and_test([tx], self.nodes[1])
self.log.debug("Check that node[1] will send the tx to node[0] even though it is already in the mempool")
- connect_nodes(self.nodes[1], 0)
+ self.connect_nodes(1, 0)
with self.nodes[1].assert_debug_log(["Force relaying tx {} from peer=0".format(txid)]):
p2p_rebroadcast_wallet.send_txs_and_test([tx], self.nodes[1])
self.wait_until(lambda: txid in self.nodes[0].getrawmempool())
@@ -141,18 +153,32 @@ class P2PPermissionsTests(BitcoinTestFramework):
self.log.debug("Check that node[1] will not send an invalid tx to node[0]")
tx.vout[0].nValue += 1
txid = tx.rehash()
+ # Send the transaction twice. The first time, it'll be rejected by ATMP because it conflicts
+ # with a mempool transaction. The second time, it'll be in the recentRejects filter.
+ p2p_rebroadcast_wallet.send_txs_and_test(
+ [tx],
+ self.nodes[1],
+ success=False,
+ reject_reason='{} from peer=0 was not accepted: txn-mempool-conflict'.format(txid)
+ )
+
p2p_rebroadcast_wallet.send_txs_and_test(
[tx],
self.nodes[1],
success=False,
- reject_reason='Not relaying non-mempool transaction {} from forcerelay peer=0'.format(txid),
+ reject_reason='Not relaying non-mempool transaction {} from forcerelay peer=0'.format(txid)
)
def checkpermission(self, args, expectedPermissions, whitelisted):
+ if whitelisted is not None:
+ args = [*args, '-deprecatedrpc=whitelisted']
self.restart_node(1, args)
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
- assert_equal(peerinfo['whitelisted'], whitelisted)
+ if whitelisted is None:
+ assert 'whitelisted' not in peerinfo
+ else:
+ assert_equal(peerinfo['whitelisted'], whitelisted)
assert_equal(len(expectedPermissions), len(peerinfo['permissions']))
for p in expectedPermissions:
if not p in peerinfo['permissions']:
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 29735b0fb3..a9d8b12d70 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -37,7 +37,6 @@ from test_framework.messages import (
msg_tx,
msg_block,
msg_no_witness_tx,
- msg_verack,
ser_uint256,
ser_vector,
sha256,
@@ -81,8 +80,6 @@ from test_framework.script import (
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
- disconnect_nodes,
softfork_active,
hex_str_to_bytes,
assert_raises_rpc_error,
@@ -148,7 +145,7 @@ def test_witness_block(node, p2p, block, accepted, with_witness=True, reason=Non
class TestP2PConn(P2PInterface):
def __init__(self, wtxidrelay=False):
- super().__init__()
+ super().__init__(wtxidrelay=wtxidrelay)
self.getdataset = set()
self.last_wtxidrelay = []
self.lastgetdata = []
@@ -159,13 +156,6 @@ class TestP2PConn(P2PInterface):
def on_inv(self, message):
pass
- def on_version(self, message):
- if self.wtxidrelay:
- super().on_version(message)
- else:
- self.send_message(msg_verack())
- self.nServices = message.nServices
-
def on_getdata(self, message):
self.lastgetdata = message.inv
for inv in message.inv:
@@ -233,8 +223,8 @@ class SegWitTest(BitcoinTestFramework):
def setup_network(self):
self.setup_nodes()
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(0, 2)
self.sync_all()
# Helper functions
@@ -498,7 +488,7 @@ class SegWitTest(BitcoinTestFramework):
# node2 doesn't need to be connected for this test.
# (If it's connected, node0 may propagate an invalid block to it over
# compact blocks and the nodes would have inconsistent tips.)
- disconnect_nodes(self.nodes[0], 2)
+ self.disconnect_nodes(0, 2)
# Create two outputs, a p2wsh and p2sh-p2wsh
witness_program = CScript([OP_TRUE])
@@ -560,7 +550,7 @@ class SegWitTest(BitcoinTestFramework):
# TODO: support multiple acceptable reject reasons.
test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 2)
self.utxo.pop(0)
self.utxo.append(UTXO(txid, 2, value))
@@ -1945,7 +1935,7 @@ class SegWitTest(BitcoinTestFramework):
"""Test the behavior of starting up a segwit-aware node after the softfork has activated."""
self.restart_node(2, extra_args=["-segwitheight={}".format(SEGWIT_HEIGHT)])
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 2)
# We reconnect more than 100 blocks, give it plenty of time
self.sync_blocks(timeout=240)
@@ -2099,14 +2089,14 @@ class SegWitTest(BitcoinTestFramework):
raw = self.nodes[0].createrawtransaction([{"txid": unspent['txid'], "vout": unspent['vout']}], {self.nodes[0].getnewaddress(): 1})
tx = FromHex(CTransaction(), raw)
- assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
+ assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, hexstring=serialize_with_bogus_witness(tx).hex(), iswitness=True)
with self.nodes[0].assert_debug_log(['Superfluous witness record']):
self.test_node.send_and_ping(msg_bogus_tx(tx))
raw = self.nodes[0].signrawtransactionwithwallet(raw)
assert raw['complete']
raw = raw['hex']
tx = FromHex(CTransaction(), raw)
- assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
+ assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, hexstring=serialize_with_bogus_witness(tx).hex(), iswitness=True)
with self.nodes[0].assert_debug_log(['Unknown transaction optional data']):
self.test_node.send_and_ping(msg_bogus_tx(tx))
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index ce12ce26ce..47832b04bf 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -57,8 +57,10 @@ class TimeoutsTest(BitcoinTestFramework):
assert no_version_node.is_connected
assert no_send_node.is_connected
- no_verack_node.send_message(msg_ping())
- no_version_node.send_message(msg_ping())
+ with self.nodes[0].assert_debug_log(['Unsupported message "ping" prior to verack from peer=0']):
+ no_verack_node.send_message(msg_ping())
+ with self.nodes[0].assert_debug_log(['non-version message before version handshake. Message "ping" from peer=1']):
+ no_version_node.send_message(msg_ping())
sleep(1)
diff --git a/test/functional/p2p_tx_download.py b/test/functional/p2p_tx_download.py
index 16d9302db8..8a751c6b54 100755
--- a/test/functional/p2p_tx_download.py
+++ b/test/functional/p2p_tx_download.py
@@ -30,8 +30,8 @@ import time
class TestP2PConn(P2PInterface):
- def __init__(self):
- super().__init__()
+ def __init__(self, wtxidrelay=True):
+ super().__init__(wtxidrelay=wtxidrelay)
self.tx_getdata_count = 0
def on_getdata(self, message):
@@ -47,6 +47,7 @@ TXID_RELAY_DELAY = 2 # seconds
OVERLOADED_PEER_DELAY = 2 # seconds
MAX_GETDATA_IN_FLIGHT = 100
MAX_PEER_TX_ANNOUNCEMENTS = 5000
+NONPREF_PEER_TX_DELAY = 2
# Python test constants
NUM_INBOUND = 10
@@ -168,8 +169,6 @@ class TxDownloadTest(BitcoinTestFramework):
assert_equal(peer_fallback.tx_getdata_count, 0)
self.nodes[0].setmocktime(int(time.time()) + GETDATA_TX_INTERVAL + 1) # Wait for request to peer_expiry to expire
peer_fallback.wait_until(lambda: peer_fallback.tx_getdata_count >= 1, timeout=1)
- with p2p_lock:
- assert_equal(peer_fallback.tx_getdata_count, 1)
self.restart_node(0) # reset mocktime
def test_disconnect_fallback(self):
@@ -187,8 +186,6 @@ class TxDownloadTest(BitcoinTestFramework):
peer_disconnect.peer_disconnect()
peer_disconnect.wait_for_disconnect()
peer_fallback.wait_until(lambda: peer_fallback.tx_getdata_count >= 1, timeout=1)
- with p2p_lock:
- assert_equal(peer_fallback.tx_getdata_count, 1)
def test_notfound_fallback(self):
self.log.info('Check that notfounds will select another peer for download immediately')
@@ -204,17 +201,42 @@ class TxDownloadTest(BitcoinTestFramework):
assert_equal(peer_fallback.tx_getdata_count, 0)
peer_notfound.send_and_ping(msg_notfound(vec=[CInv(MSG_WTX, WTXID)])) # Send notfound, so that fallback peer is selected
peer_fallback.wait_until(lambda: peer_fallback.tx_getdata_count >= 1, timeout=1)
- with p2p_lock:
- assert_equal(peer_fallback.tx_getdata_count, 1)
- def test_preferred_inv(self):
- self.log.info('Check that invs from preferred peers are downloaded immediately')
- self.restart_node(0, extra_args=['-whitelist=noban@127.0.0.1'])
+ def test_preferred_inv(self, preferred=False):
+ if preferred:
+ self.log.info('Check invs from preferred peers are downloaded immediately')
+ self.restart_node(0, extra_args=['-whitelist=noban@127.0.0.1'])
+ else:
+ self.log.info('Check invs from non-preferred peers are downloaded after {} s'.format(NONPREF_PEER_TX_DELAY))
+ mock_time = int(time.time() + 1)
+ self.nodes[0].setmocktime(mock_time)
peer = self.nodes[0].add_p2p_connection(TestP2PConn())
peer.send_message(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
- peer.wait_until(lambda: peer.tx_getdata_count >= 1, timeout=1)
+ peer.sync_with_ping()
+ if preferred:
+ peer.wait_until(lambda: peer.tx_getdata_count >= 1, timeout=1)
+ else:
+ with p2p_lock:
+ assert_equal(peer.tx_getdata_count, 0)
+ self.nodes[0].setmocktime(mock_time + NONPREF_PEER_TX_DELAY)
+ peer.wait_until(lambda: peer.tx_getdata_count >= 1, timeout=1)
+
+ def test_txid_inv_delay(self, glob_wtxid=False):
+ self.log.info('Check that inv from a txid-relay peers are delayed by {} s, with a wtxid peer {}'.format(TXID_RELAY_DELAY, glob_wtxid))
+ self.restart_node(0, extra_args=['-whitelist=noban@127.0.0.1'])
+ mock_time = int(time.time() + 1)
+ self.nodes[0].setmocktime(mock_time)
+ peer = self.nodes[0].add_p2p_connection(TestP2PConn(wtxidrelay=False))
+ if glob_wtxid:
+ # Add a second wtxid-relay connection otherwise TXID_RELAY_DELAY is waived in
+ # lack of wtxid-relay peers
+ self.nodes[0].add_p2p_connection(TestP2PConn(wtxidrelay=True))
+ peer.send_message(msg_inv([CInv(t=MSG_TX, h=0xff11ff11)]))
+ peer.sync_with_ping()
with p2p_lock:
- assert_equal(peer.tx_getdata_count, 1)
+ assert_equal(peer.tx_getdata_count, 0 if glob_wtxid else 1)
+ self.nodes[0].setmocktime(mock_time + TXID_RELAY_DELAY)
+ peer.wait_until(lambda: peer.tx_getdata_count >= 1, timeout=1)
def test_large_inv_batch(self):
self.log.info('Test how large inv batches are handled with relay permission')
@@ -229,8 +251,6 @@ class TxDownloadTest(BitcoinTestFramework):
peer.send_message(msg_inv([CInv(t=MSG_WTX, h=wtxid) for wtxid in range(MAX_PEER_TX_ANNOUNCEMENTS + 1)]))
peer.wait_until(lambda: peer.tx_getdata_count == MAX_PEER_TX_ANNOUNCEMENTS)
peer.sync_with_ping()
- with p2p_lock:
- assert_equal(peer.tx_getdata_count, MAX_PEER_TX_ANNOUNCEMENTS)
def test_spurious_notfound(self):
self.log.info('Check that spurious notfound is ignored')
@@ -242,6 +262,9 @@ class TxDownloadTest(BitcoinTestFramework):
self.test_disconnect_fallback()
self.test_notfound_fallback()
self.test_preferred_inv()
+ self.test_preferred_inv(True)
+ self.test_txid_inv_delay()
+ self.test_txid_inv_delay(True)
self.test_large_inv_batch()
self.test_spurious_notfound()
diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py
index 36b434bce3..e7a05d8547 100755
--- a/test/functional/p2p_unrequested_blocks.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -60,7 +60,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
)
@@ -284,7 +283,7 @@ class AcceptBlockTest(BitcoinTestFramework):
test_node.wait_for_disconnect()
# 9. Connect node1 to node0 and ensure it is able to sync
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks([self.nodes[0], self.nodes[1]])
self.log.info("Successfully synced nodes 1 and 0")
diff --git a/test/functional/rpc_estimatefee.py b/test/functional/rpc_estimatefee.py
index 1fff9e1512..81862ac69e 100755
--- a/test/functional/rpc_estimatefee.py
+++ b/test/functional/rpc_estimatefee.py
@@ -28,7 +28,7 @@ class EstimateFeeTest(BitcoinTestFramework):
# 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(-8, "Invalid estimate_mode parameter", self.nodes[0].estimatesmartfee, 1, 'foo')
+ 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')
@@ -41,6 +41,8 @@ class EstimateFeeTest(BitcoinTestFramework):
self.nodes[0].estimatesmartfee(1)
# self.nodes[0].estimatesmartfee(1, None)
self.nodes[0].estimatesmartfee(1, 'ECONOMICAL')
+ self.nodes[0].estimatesmartfee(1, 'unset')
+ self.nodes[0].estimatesmartfee(1, 'conservative')
self.nodes[0].estimaterawfee(1)
self.nodes[0].estimaterawfee(1, None)
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 7a729f7bc1..569471dc87 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -5,14 +5,15 @@
"""Test the fundrawtransaction RPC."""
from decimal import Decimal
+from test_framework.descriptors import descsum_create
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
+ assert_approx,
assert_equal,
assert_fee_amount,
assert_greater_than,
assert_greater_than_or_equal,
assert_raises_rpc_error,
- connect_nodes,
count_bytes,
find_vout_for_address,
)
@@ -38,10 +39,10 @@ class RawTransactionsTest(BitcoinTestFramework):
def setup_network(self):
self.setup_nodes()
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 2)
- connect_nodes(self.nodes[0], 2)
- connect_nodes(self.nodes[0], 3)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 2)
+ self.connect_nodes(0, 2)
+ self.connect_nodes(0, 3)
def run_test(self):
self.log.info("Connect nodes, set fees, generate blocks, and sync")
@@ -101,17 +102,19 @@ class RawTransactionsTest(BitcoinTestFramework):
rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]})
assert_equal(rawmatch["changepos"], -1)
+ self.nodes[3].createwallet(wallet_name="wwatch", disable_private_keys=True)
+ wwatch = self.nodes[3].get_wallet_rpc('wwatch')
watchonly_address = self.nodes[0].getnewaddress()
watchonly_pubkey = self.nodes[0].getaddressinfo(watchonly_address)["pubkey"]
self.watchonly_amount = Decimal(200)
- self.nodes[3].importpubkey(watchonly_pubkey, "", True)
+ wwatch.importpubkey(watchonly_pubkey, "", True)
self.watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, self.watchonly_amount)
# Lock UTXO so nodes[0] doesn't accidentally spend it
self.watchonly_vout = find_vout_for_address(self.nodes[0], self.watchonly_txid, watchonly_address)
self.nodes[0].lockunspent(False, [{"txid": self.watchonly_txid, "vout": self.watchonly_vout}])
- self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), self.watchonly_amount / 10)
+ self.nodes[0].sendtoaddress(self.nodes[3].get_wallet_rpc(self.default_wallet_name).getnewaddress(), self.watchonly_amount / 10)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
@@ -120,6 +123,8 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all()
+ wwatch.unloadwallet()
+
def test_simple(self):
self.log.info("Test fundrawtxn")
inputs = [ ]
@@ -407,7 +412,7 @@ class RawTransactionsTest(BitcoinTestFramework):
addr1Obj = self.nodes[1].getaddressinfo(addr1)
addr2Obj = self.nodes[1].getaddressinfo(addr2)
- mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
+ mSigObj = self.nodes[3].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
inputs = []
outputs = {mSigObj:1.1}
@@ -439,7 +444,7 @@ class RawTransactionsTest(BitcoinTestFramework):
addr4Obj = self.nodes[1].getaddressinfo(addr4)
addr5Obj = self.nodes[1].getaddressinfo(addr5)
- mSigObj = self.nodes[1].addmultisigaddress(
+ mSigObj = self.nodes[1].createmultisig(
4,
[
addr1Obj['pubkey'],
@@ -465,7 +470,7 @@ class RawTransactionsTest(BitcoinTestFramework):
def test_spend_2of2(self):
"""Spend a 2-of-2 multisig transaction over fundraw."""
- self.log.info("Test fundrawtxn spending 2-of-2 multisig")
+ self.log.info("Test fundpsbt spending 2-of-2 multisig")
# Create 2-of-2 addr.
addr1 = self.nodes[2].getnewaddress()
@@ -474,13 +479,18 @@ class RawTransactionsTest(BitcoinTestFramework):
addr1Obj = self.nodes[2].getaddressinfo(addr1)
addr2Obj = self.nodes[2].getaddressinfo(addr2)
- mSigObj = self.nodes[2].addmultisigaddress(
+ self.nodes[2].createwallet(wallet_name='wmulti', disable_private_keys=True)
+ wmulti = self.nodes[2].get_wallet_rpc('wmulti')
+ w2 = self.nodes[2].get_wallet_rpc(self.default_wallet_name)
+ mSigObj = wmulti.addmultisigaddress(
2,
[
addr1Obj['pubkey'],
addr2Obj['pubkey'],
]
)['address']
+ if not self.options.descriptors:
+ wmulti.importaddress(mSigObj)
# Send 1.2 BTC to msig addr.
self.nodes[0].sendtoaddress(mSigObj, 1.2)
@@ -490,22 +500,39 @@ class RawTransactionsTest(BitcoinTestFramework):
oldBalance = self.nodes[1].getbalance()
inputs = []
outputs = {self.nodes[1].getnewaddress():1.1}
- rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
- fundedTx = self.nodes[2].fundrawtransaction(rawtx)
+ funded_psbt = wmulti.walletcreatefundedpsbt(inputs=inputs, outputs=outputs, options={'changeAddress': w2.getrawchangeaddress()})['psbt']
- signedTx = self.nodes[2].signrawtransactionwithwallet(fundedTx['hex'])
- self.nodes[2].sendrawtransaction(signedTx['hex'])
+ signed_psbt = w2.walletprocesspsbt(funded_psbt)
+ final_psbt = w2.finalizepsbt(signed_psbt['psbt'])
+ self.nodes[2].sendrawtransaction(final_psbt['hex'])
self.nodes[2].generate(1)
self.sync_all()
# Make sure funds are received at node1.
assert_equal(oldBalance+Decimal('1.10000000'), self.nodes[1].getbalance())
+ wmulti.unloadwallet()
+
def test_locked_wallet(self):
- self.log.info("Test fundrawtxn with locked wallet")
+ self.log.info("Test fundrawtxn with locked wallet and hardened derivation")
self.nodes[1].encryptwallet("test")
+ if self.options.descriptors:
+ self.nodes[1].walletpassphrase('test', 10)
+ self.nodes[1].importdescriptors([{
+ 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPdYeeZbPSKd2KYLmeVKtcFA7kqCxDvDR13MQ6us8HopUR2wLcS2ZKPhLyKsqpDL2FtL73LMHcgoCL7DXsciA8eX8nbjCR2eG/0h/*h)'),
+ 'timestamp': 'now',
+ 'active': True
+ },
+ {
+ 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPdYeeZbPSKd2KYLmeVKtcFA7kqCxDvDR13MQ6us8HopUR2wLcS2ZKPhLyKsqpDL2FtL73LMHcgoCL7DXsciA8eX8nbjCR2eG/1h/*h)'),
+ 'timestamp': 'now',
+ 'active': True,
+ 'internal': True
+ }])
+ self.nodes[1].walletlock()
+
# Drain the keypool.
self.nodes[1].getnewaddress()
self.nodes[1].getrawchangeaddress()
@@ -622,7 +649,25 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {self.nodes[2].getnewaddress(): self.watchonly_amount / 2}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
- result = self.nodes[3].fundrawtransaction(rawtx, {'includeWatching': True })
+ self.nodes[3].loadwallet('wwatch')
+ wwatch = self.nodes[3].get_wallet_rpc('wwatch')
+ # Setup change addresses for the watchonly wallet
+ desc_import = [{
+ "desc": descsum_create("wpkh(tpubD6NzVbkrYhZ4YNXVQbNhMK1WqguFsUXceaVJKbmno2aZ3B6QfbMeraaYvnBSGpV3vxLyTTK9DYT1yoEck4XUScMzXoQ2U2oSmE2JyMedq3H/1/*)"),
+ "timestamp": "now",
+ "internal": True,
+ "active": True,
+ "keypool": True,
+ "range": [0, 100],
+ "watchonly": True,
+ }]
+ if self.options.descriptors:
+ wwatch.importdescriptors(desc_import)
+ else:
+ wwatch.importmulti(desc_import)
+
+ # Backward compatibility test (2nd params is includeWatching)
+ result = wwatch.fundrawtransaction(rawtx, True)
res_dec = self.nodes[0].decoderawtransaction(result["hex"])
assert_equal(len(res_dec["vin"]), 1)
assert_equal(res_dec["vin"][0]["txid"], self.watchonly_txid)
@@ -630,6 +675,8 @@ class RawTransactionsTest(BitcoinTestFramework):
assert "fee" in result.keys()
assert_greater_than(result["changepos"], -1)
+ wwatch.unloadwallet()
+
def test_all_watched_funds(self):
self.log.info("Test fundrawtxn using entirety of watched funds")
@@ -637,17 +684,19 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {self.nodes[2].getnewaddress(): self.watchonly_amount}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
- # Backward compatibility test (2nd param is includeWatching).
- result = self.nodes[3].fundrawtransaction(rawtx, True)
+ self.nodes[3].loadwallet('wwatch')
+ wwatch = self.nodes[3].get_wallet_rpc('wwatch')
+ w3 = self.nodes[3].get_wallet_rpc(self.default_wallet_name)
+ result = wwatch.fundrawtransaction(rawtx, {'includeWatching': True, 'changeAddress': w3.getrawchangeaddress(), 'subtractFeeFromOutputs': [0]})
res_dec = self.nodes[0].decoderawtransaction(result["hex"])
- assert_equal(len(res_dec["vin"]), 2)
- assert res_dec["vin"][0]["txid"] == self.watchonly_txid or res_dec["vin"][1]["txid"] == self.watchonly_txid
+ assert_equal(len(res_dec["vin"]), 1)
+ assert res_dec["vin"][0]["txid"] == self.watchonly_txid
assert_greater_than(result["fee"], 0)
- assert_greater_than(result["changepos"], -1)
- assert_equal(result["fee"] + res_dec["vout"][result["changepos"]]["value"], self.watchonly_amount / 10)
+ assert_equal(result["changepos"], -1)
+ assert_equal(result["fee"] + res_dec["vout"][0]["value"], self.watchonly_amount)
- signedtx = self.nodes[3].signrawtransactionwithwallet(result["hex"])
+ signedtx = wwatch.signrawtransactionwithwallet(result["hex"])
assert not signedtx["complete"]
signedtx = self.nodes[0].signrawtransactionwithwallet(signedtx["hex"])
assert signedtx["complete"]
@@ -655,22 +704,91 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all()
- def test_option_feerate(self):
- self.log.info("Test fundrawtxn feeRate option")
+ wwatch.unloadwallet()
+ def test_option_feerate(self):
+ self.log.info("Test fundrawtxn with explicit fee rates (fee_rate sat/vB and feeRate BTC/kvB)")
+ node = self.nodes[3]
# Make sure there is exactly one input so coin selection can't skew the result.
assert_equal(len(self.nodes[3].listunspent(1)), 1)
-
inputs = []
- outputs = {self.nodes[3].getnewaddress() : 1}
- rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
- result = self.nodes[3].fundrawtransaction(rawtx) # uses self.min_relay_tx_fee (set by settxfee)
- result2 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee})
- result3 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 10 * self.min_relay_tx_fee})
- assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[3].fundrawtransaction, rawtx, {"feeRate": 1})
+ outputs = {node.getnewaddress() : 1}
+ rawtx = node.createrawtransaction(inputs, outputs)
+
+ result = node.fundrawtransaction(rawtx) # uses self.min_relay_tx_fee (set by settxfee)
+ btc_kvb_to_sat_vb = 100000 # (1e5)
+ result1 = node.fundrawtransaction(rawtx, {"fee_rate": str(2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee)})
+ result2 = node.fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee})
+ result3 = node.fundrawtransaction(rawtx, {"fee_rate": 10 * btc_kvb_to_sat_vb * self.min_relay_tx_fee})
+ result4 = node.fundrawtransaction(rawtx, {"feeRate": str(10 * self.min_relay_tx_fee)})
+ # Test that funding non-standard "zero-fee" transactions is valid.
+ result5 = self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 0})
+ result6 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 0})
+
result_fee_rate = result['fee'] * 1000 / count_bytes(result['hex'])
+ assert_fee_amount(result1['fee'], count_bytes(result2['hex']), 2 * result_fee_rate)
assert_fee_amount(result2['fee'], count_bytes(result2['hex']), 2 * result_fee_rate)
assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate)
+ assert_fee_amount(result4['fee'], count_bytes(result3['hex']), 10 * result_fee_rate)
+ assert_fee_amount(result5['fee'], count_bytes(result5['hex']), 0)
+ assert_fee_amount(result6['fee'], count_bytes(result6['hex']), 0)
+
+ # With no arguments passed, expect fee of 141 satoshis.
+ assert_approx(node.fundrawtransaction(rawtx)["fee"], vexp=0.00000141, vspan=0.00000001)
+ # Expect fee to be 10,000x higher when an explicit fee rate 10,000x greater is specified.
+ result = node.fundrawtransaction(rawtx, {"fee_rate": 10000})
+ assert_approx(result["fee"], vexp=0.0141, vspan=0.0001)
+
+ self.log.info("Test fundrawtxn with invalid estimate_mode settings")
+ for k, v in {"number": 42, "object": {"foo": "bar"}}.items():
+ assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k),
+ node.fundrawtransaction, rawtx, {"estimate_mode": v, "conf_target": 0.1, "add_inputs": True})
+ for mode in ["", "foo", Decimal("3.141592")]:
+ assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
+ node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": 0.1, "add_inputs": True})
+
+ self.log.info("Test fundrawtxn with invalid conf_target settings")
+ for mode in ["unset", "economical", "conservative"]:
+ self.log.debug("{}".format(mode))
+ for k, v in {"string": "", "object": {"foo": "bar"}}.items():
+ assert_raises_rpc_error(-3, "Expected type number for conf_target, got {}".format(k),
+ node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": v, "add_inputs": True})
+ for n in [-1, 0, 1009]:
+ assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h
+ node.fundrawtransaction, rawtx, {"estimate_mode": mode, "conf_target": n, "add_inputs": True})
+
+ self.log.info("Test invalid fee rate settings")
+ for param, value in {("fee_rate", 100000), ("feeRate", 1.000)}:
+ assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
+ node.fundrawtransaction, rawtx, {param: value, "add_inputs": True})
+ assert_raises_rpc_error(-3, "Amount out of range",
+ node.fundrawtransaction, rawtx, {param: -1, "add_inputs": True})
+ assert_raises_rpc_error(-3, "Amount is not a number or string",
+ node.fundrawtransaction, rawtx, {param: {"foo": "bar"}, "add_inputs": True})
+ assert_raises_rpc_error(-3, "Invalid amount",
+ node.fundrawtransaction, rawtx, {param: "", "add_inputs": True})
+
+ self.log.info("Test min fee rate checks are bypassed with fundrawtxn, e.g. a fee_rate under 1 sat/vB is allowed")
+ node.fundrawtransaction(rawtx, {"fee_rate": 0.99999999, "add_inputs": True})
+ node.fundrawtransaction(rawtx, {"feeRate": 0.00000999, "add_inputs": True})
+
+ self.log.info("- raises RPC error if both feeRate and fee_rate are passed")
+ assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)",
+ node.fundrawtransaction, rawtx, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True})
+
+ self.log.info("- raises RPC error if both feeRate and estimate_mode passed")
+ assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate",
+ node.fundrawtransaction, rawtx, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True})
+
+ for param in ["feeRate", "fee_rate"]:
+ self.log.info("- raises RPC error if both {} and conf_target are passed".format(param))
+ assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation "
+ "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param),
+ node.fundrawtransaction, rawtx, {param: 1, "conf_target": 1, "add_inputs": True})
+
+ self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed")
+ assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate",
+ node.fundrawtransaction, rawtx, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True})
def test_address_reuse(self):
"""Test no address reuse occurs."""
@@ -698,12 +816,32 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {self.nodes[2].getnewaddress(): 1}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
+ # Test subtract fee from outputs with feeRate (BTC/kvB)
result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee)
self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list
self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses self.min_relay_tx_fee (set by settxfee)
self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee}),
self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee, "subtractFeeFromOutputs": [0]}),]
+ dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result]
+ output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)]
+ change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)]
+ assert_equal(result[0]['fee'], result[1]['fee'], result[2]['fee'])
+ assert_equal(result[3]['fee'], result[4]['fee'])
+ assert_equal(change[0], change[1])
+ assert_equal(output[0], output[1])
+ assert_equal(output[0], output[2] + result[2]['fee'])
+ assert_equal(change[0] + result[0]['fee'], change[2])
+ assert_equal(output[3], output[4] + result[4]['fee'])
+ assert_equal(change[3] + result[3]['fee'], change[4])
+
+ # Test subtract fee from outputs with fee_rate (sat/vB)
+ btc_kvb_to_sat_vb = 100000 # (1e5)
+ result = [self.nodes[3].fundrawtransaction(rawtx), # uses self.min_relay_tx_fee (set by settxfee)
+ self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": []}), # empty subtraction list
+ self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0]}), # uses self.min_relay_tx_fee (set by settxfee)
+ self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee}),
+ self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee, "subtractFeeFromOutputs": [0]}),]
dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result]
output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)]
change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)]
diff --git a/test/functional/rpc_getblockfilter.py b/test/functional/rpc_getblockfilter.py
index 8fa36445cd..c3c3622cf9 100755
--- a/test/functional/rpc_getblockfilter.py
+++ b/test/functional/rpc_getblockfilter.py
@@ -7,7 +7,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal, assert_is_hex_string, assert_raises_rpc_error,
- connect_nodes, disconnect_nodes
)
FILTER_TYPES = ["basic"]
@@ -20,7 +19,7 @@ class GetBlockFilterTest(BitcoinTestFramework):
def run_test(self):
# Create two chains by disconnecting nodes 0 & 1, mining, then reconnecting
- disconnect_nodes(self.nodes[0], 1)
+ self.disconnect_nodes(0, 1)
self.nodes[0].generate(3)
self.nodes[1].generate(4)
@@ -29,7 +28,7 @@ class GetBlockFilterTest(BitcoinTestFramework):
chain0_hashes = [self.nodes[0].getblockhash(block_height) for block_height in range(4)]
# Reorg node 0 to a new chain
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks()
assert_equal(self.nodes[0].getblockcount(), 4)
diff --git a/test/functional/rpc_getpeerinfo_deprecation.py b/test/functional/rpc_getpeerinfo_deprecation.py
index 287c40ae3e..340a66e12f 100755
--- a/test/functional/rpc_getpeerinfo_deprecation.py
+++ b/test/functional/rpc_getpeerinfo_deprecation.py
@@ -5,7 +5,6 @@
"""Test deprecation of getpeerinfo RPC fields."""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import connect_nodes
class GetpeerinfoDeprecationTest(BitcoinTestFramework):
@@ -26,7 +25,7 @@ class GetpeerinfoDeprecationTest(BitcoinTestFramework):
def test_addnode_deprecation(self):
self.restart_node(1, ["-deprecatedrpc=getpeerinfo_addnode"])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.log.info("Test getpeerinfo by default no longer returns an addnode field")
assert "addnode" not in self.nodes[0].getpeerinfo()[0].keys()
diff --git a/test/functional/rpc_invalidateblock.py b/test/functional/rpc_invalidateblock.py
index e788e75557..f884b8d293 100755
--- a/test/functional/rpc_invalidateblock.py
+++ b/test/functional/rpc_invalidateblock.py
@@ -8,7 +8,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR
from test_framework.util import (
assert_equal,
- connect_nodes,
)
@@ -32,7 +31,7 @@ class InvalidateTest(BitcoinTestFramework):
assert_equal(self.nodes[1].getblockcount(), 6)
self.log.info("Connect nodes to force a reorg")
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks(self.nodes[0:2])
assert_equal(self.nodes[0].getblockcount(), 6)
badhash = self.nodes[1].getblockhash(2)
@@ -43,7 +42,7 @@ class InvalidateTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getbestblockhash(), besthash_n0)
self.log.info("Make sure we won't reorg to a lower work chain:")
- connect_nodes(self.nodes[1], 2)
+ self.connect_nodes(1, 2)
self.log.info("Sync node 2 to node 1 so both have 6 blocks")
self.sync_blocks(self.nodes[1:3])
assert_equal(self.nodes[2].getblockcount(), 6)
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index b8a04f494d..2efd090733 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -21,10 +21,8 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_approx,
assert_equal,
- assert_greater_than_or_equal,
assert_greater_than,
assert_raises_rpc_error,
- connect_nodes,
p2p_port,
)
@@ -52,9 +50,13 @@ class NetTest(BitcoinTestFramework):
def run_test(self):
# Get out of IBD for the minfeefilter and getpeerinfo tests.
self.nodes[0].generate(101)
- # Connect nodes both ways.
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 0)
+
+ # By default, the test framework sets up an addnode connection from
+ # node 1 --> node0. By connecting node0 --> node 1, we're left with
+ # the two nodes being connected both ways.
+ # Topology will look like: node0 <--> node1
+ self.connect_nodes(0, 1)
+ self.sync_all()
self.test_connection_count()
self.test_getpeerinfo()
@@ -69,36 +71,52 @@ class NetTest(BitcoinTestFramework):
# After using `connect_nodes` to connect nodes 0 and 1 to each other.
assert_equal(self.nodes[0].getconnectioncount(), 2)
+ def test_getpeerinfo(self):
+ self.log.info("Test getpeerinfo")
+ # Create a few getpeerinfo last_block/last_transaction values.
+ if self.is_wallet_compiled():
+ self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
+ self.nodes[1].generate(1)
+ self.sync_all()
+ time_now = int(time.time())
+ peer_info = [x.getpeerinfo() for x in self.nodes]
+ # Verify last_block and last_transaction keys/values.
+ for node, peer, field in product(range(self.num_nodes), range(2), ['last_block', 'last_transaction']):
+ assert field in peer_info[node][peer].keys()
+ if peer_info[node][peer][field] != 0:
+ assert_approx(peer_info[node][peer][field], time_now, vspan=60)
+ # check both sides of bidirectional connection between nodes
+ # the address bound to on one side will be the source address for the other node
+ assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr'])
+ assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr'])
+ assert_equal(peer_info[0][0]['minfeefilter'], Decimal("0.00000500"))
+ assert_equal(peer_info[1][0]['minfeefilter'], Decimal("0.00001000"))
+ # check the `servicesnames` field
+ for info in peer_info:
+ assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"])
+
+ assert_equal(peer_info[0][0]['connection_type'], 'inbound')
+ assert_equal(peer_info[0][1]['connection_type'], 'manual')
+
+ assert_equal(peer_info[1][0]['connection_type'], 'manual')
+ assert_equal(peer_info[1][1]['connection_type'], 'inbound')
+
def test_getnettotals(self):
self.log.info("Test getnettotals")
- # getnettotals totalbytesrecv and totalbytessent should be
- # consistent with getpeerinfo. Since the RPC calls are not atomic,
- # and messages might have been recvd or sent between RPC calls, call
- # getnettotals before and after and verify that the returned values
- # from getpeerinfo are bounded by those values.
+ # Test getnettotals and getpeerinfo by doing a ping. The bytes
+ # sent/received should increase by at least the size of one ping (32
+ # bytes) and one pong (32 bytes).
net_totals_before = self.nodes[0].getnettotals()
- peer_info = self.nodes[0].getpeerinfo()
- net_totals_after = self.nodes[0].getnettotals()
- assert_equal(len(peer_info), 2)
- peers_recv = sum([peer['bytesrecv'] for peer in peer_info])
- peers_sent = sum([peer['bytessent'] for peer in peer_info])
-
- assert_greater_than_or_equal(peers_recv, net_totals_before['totalbytesrecv'])
- assert_greater_than_or_equal(net_totals_after['totalbytesrecv'], peers_recv)
- assert_greater_than_or_equal(peers_sent, net_totals_before['totalbytessent'])
- assert_greater_than_or_equal(net_totals_after['totalbytessent'], peers_sent)
-
- # test getnettotals and getpeerinfo by doing a ping
- # the bytes sent/received should change
- # note ping and pong are 32 bytes each
+ peer_info_before = self.nodes[0].getpeerinfo()
+
self.nodes[0].ping()
- self.wait_until(lambda: (self.nodes[0].getnettotals()['totalbytessent'] >= net_totals_after['totalbytessent'] + 32 * 2), timeout=1)
- self.wait_until(lambda: (self.nodes[0].getnettotals()['totalbytesrecv'] >= net_totals_after['totalbytesrecv'] + 32 * 2), timeout=1)
+ self.wait_until(lambda: (self.nodes[0].getnettotals()['totalbytessent'] >= net_totals_before['totalbytessent'] + 32 * 2), timeout=1)
+ self.wait_until(lambda: (self.nodes[0].getnettotals()['totalbytesrecv'] >= net_totals_before['totalbytesrecv'] + 32 * 2), timeout=1)
- peer_info_after_ping = self.nodes[0].getpeerinfo()
- for before, after in zip(peer_info, peer_info_after_ping):
- assert_greater_than_or_equal(after['bytesrecv_per_msg'].get('pong', 0), before['bytesrecv_per_msg'].get('pong', 0) + 32)
- assert_greater_than_or_equal(after['bytessent_per_msg'].get('ping', 0), before['bytessent_per_msg'].get('ping', 0) + 32)
+ for peer_before in peer_info_before:
+ peer_after = lambda: next(p for p in self.nodes[0].getpeerinfo() if p['id'] == peer_before['id'])
+ self.wait_until(lambda: peer_after()['bytesrecv_per_msg'].get('pong', 0) >= peer_before['bytesrecv_per_msg'].get('pong', 0) + 32, timeout=1)
+ self.wait_until(lambda: peer_after()['bytessent_per_msg'].get('ping', 0) >= peer_before['bytessent_per_msg'].get('ping', 0) + 32, timeout=1)
def test_getnetworkinfo(self):
self.log.info("Test getnetworkinfo")
@@ -117,8 +135,8 @@ class NetTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']):
self.nodes[0].setnetworkactive(state=True)
# Connect nodes both ways.
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 0)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 0)
info = self.nodes[0].getnetworkinfo()
assert_equal(info['networkactive'], True)
@@ -151,36 +169,6 @@ class NetTest(BitcoinTestFramework):
# check that a non-existent node returns an error
assert_raises_rpc_error(-24, "Node has not been added", self.nodes[0].getaddednodeinfo, '1.1.1.1')
- def test_getpeerinfo(self):
- self.log.info("Test getpeerinfo")
- # Create a few getpeerinfo last_block/last_transaction values.
- if self.is_wallet_compiled():
- self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
- self.nodes[1].generate(1)
- self.sync_all()
- time_now = int(time.time())
- peer_info = [x.getpeerinfo() for x in self.nodes]
- # Verify last_block and last_transaction keys/values.
- for node, peer, field in product(range(self.num_nodes), range(2), ['last_block', 'last_transaction']):
- assert field in peer_info[node][peer].keys()
- if peer_info[node][peer][field] != 0:
- assert_approx(peer_info[node][peer][field], time_now, vspan=60)
- # check both sides of bidirectional connection between nodes
- # the address bound to on one side will be the source address for the other node
- assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr'])
- assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr'])
- assert_equal(peer_info[0][0]['minfeefilter'], Decimal("0.00000500"))
- assert_equal(peer_info[1][0]['minfeefilter'], Decimal("0.00001000"))
- # check the `servicesnames` field
- for info in peer_info:
- assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"])
-
- assert_equal(peer_info[0][0]['connection_type'], 'inbound')
- assert_equal(peer_info[0][1]['connection_type'], 'manual')
-
- assert_equal(peer_info[1][0]['connection_type'], 'manual')
- assert_equal(peer_info[1][1]['connection_type'], 'inbound')
-
def test_service_flags(self):
self.log.info("Test service flags")
self.nodes[0].add_p2p_connection(P2PInterface(), services=(1 << 4) | (1 << 63))
diff --git a/test/functional/rpc_preciousblock.py b/test/functional/rpc_preciousblock.py
index 8386e47411..04d55b103f 100755
--- a/test/functional/rpc_preciousblock.py
+++ b/test/functional/rpc_preciousblock.py
@@ -7,7 +7,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
)
def unidirectional_node_sync_via_rpc(node_src, node_dest):
@@ -61,7 +60,7 @@ class PreciousTest(BitcoinTestFramework):
self.log.info("Connect nodes and check no reorg occurs")
# Submit competing blocks via RPC so any reorg should occur before we proceed (no way to wait on inaction for p2p sync)
node_sync_via_rpc(self.nodes[0:2])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
assert_equal(self.nodes[0].getbestblockhash(), hashC)
assert_equal(self.nodes[1].getbestblockhash(), hashG)
self.log.info("Make Node0 prefer block G")
@@ -98,8 +97,8 @@ class PreciousTest(BitcoinTestFramework):
hashL = self.nodes[2].getbestblockhash()
self.log.info("Connect nodes and check no reorg occurs")
node_sync_via_rpc(self.nodes[1:3])
- connect_nodes(self.nodes[1], 2)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(1, 2)
+ self.connect_nodes(0, 2)
assert_equal(self.nodes[0].getbestblockhash(), hashH)
assert_equal(self.nodes[1].getbestblockhash(), hashH)
assert_equal(self.nodes[2].getbestblockhash(), hashL)
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 10aebc2b1d..b364077a9a 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -12,8 +12,6 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_raises_rpc_error,
- connect_nodes,
- disconnect_nodes,
find_output,
)
@@ -46,7 +44,7 @@ class PSBTTest(BitcoinTestFramework):
# Disconnect offline node from others
# Topology of test network is linear, so this one call is enough
- disconnect_nodes(offline_node, 1)
+ self.disconnect_nodes(0, 1)
# Create watchonly on online_node
online_node.createwallet(wallet_name='wonline', disable_private_keys=True)
@@ -80,8 +78,8 @@ class PSBTTest(BitcoinTestFramework):
wonline.unloadwallet()
# Reconnect
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(0, 2)
def assert_change_type(self, psbtx, expected_type):
"""Assert that the given PSBT has a change output with the given type."""
@@ -174,8 +172,11 @@ class PSBTTest(BitcoinTestFramework):
elif out['scriptPubKey']['addresses'][0] == p2pkh:
p2pkh_pos = out['n']
+ inputs = [{"txid": txid, "vout": p2wpkh_pos}, {"txid": txid, "vout": p2sh_p2wpkh_pos}, {"txid": txid, "vout": p2pkh_pos}]
+ outputs = [{self.nodes[1].getnewaddress(): 29.99}]
+
# spend single key from node 1
- created_psbt = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99})
+ created_psbt = self.nodes[1].walletcreatefundedpsbt(inputs, outputs)
walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(created_psbt['psbt'])
# Make sure it has both types of UTXOs
decoded = self.nodes[1].decodepsbt(walletprocesspsbt_out['psbt'])
@@ -186,15 +187,77 @@ class PSBTTest(BitcoinTestFramework):
assert_equal(walletprocesspsbt_out['complete'], True)
self.nodes[1].sendrawtransaction(self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])
- # feeRate of 0.1 BTC / KB produces a total fee slightly below -maxtxfee (~0.05280000):
- res = self.nodes[1].walletcreatefundedpsbt([{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 0.1, "add_inputs": True})
- assert_approx(res["fee"], 0.055, 0.005)
-
- # feeRate of 10 BTC / KB produces a total fee well above -maxtxfee
+ self.log.info("Test walletcreatefundedpsbt fee rate of 10000 sat/vB and 0.1 BTC/kvB produces a total fee at or slightly below -maxtxfee (~0.05290000)")
+ res1 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 10000, "add_inputs": True})
+ assert_approx(res1["fee"], 0.055, 0.005)
+ res2 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": "0.1", "add_inputs": True})
+ assert_approx(res2["fee"], 0.055, 0.005)
+
+ self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed, e.g. a fee_rate under 1 sat/vB is allowed")
+ res3 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": "0.99999999", "add_inputs": True})
+ assert_approx(res3["fee"], 0.00000381, 0.0000001)
+ res4 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.00000999, "add_inputs": True})
+ assert_approx(res4["fee"], 0.00000381, 0.0000001)
+
+ self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed and that funding non-standard 'zero-fee' transactions is valid")
+ for param in ["fee_rate", "feeRate"]:
+ assert_equal(self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {param: 0, "add_inputs": True})["fee"], 0)
+
+ self.log.info("Test invalid fee rate settings")
+ for param, value in {("fee_rate", 100000), ("feeRate", 1)}:
+ assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)",
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: value, "add_inputs": True})
+ assert_raises_rpc_error(-3, "Amount out of range",
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: -1, "add_inputs": True})
+ assert_raises_rpc_error(-3, "Amount is not a number or string",
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: {"foo": "bar"}, "add_inputs": True})
+ assert_raises_rpc_error(-3, "Invalid amount",
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {param: "", "add_inputs": True})
+
+ self.log.info("- raises RPC error if both feeRate and fee_rate are passed")
+ assert_raises_rpc_error(-8, "Cannot specify both fee_rate (sat/vB) and feeRate (BTC/kvB)",
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"fee_rate": 0.1, "feeRate": 0.1, "add_inputs": True})
+
+ self.log.info("- raises RPC error if both feeRate and estimate_mode passed")
+ assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and feeRate",
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": "economical", "feeRate": 0.1, "add_inputs": True})
+
+ for param in ["feeRate", "fee_rate"]:
+ self.log.info("- raises RPC error if both {} and conf_target are passed".format(param))
+ assert_raises_rpc_error(-8, "Cannot specify both conf_target and {}. Please provide either a confirmation "
+ "target in blocks for automatic fee estimation, or an explicit fee rate.".format(param),
+ self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {param: 1, "conf_target": 1, "add_inputs": True})
+
+ self.log.info("- raises RPC error if both fee_rate and estimate_mode are passed")
+ assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate",
+ self.nodes[1].walletcreatefundedpsbt ,inputs, outputs, 0, {"fee_rate": 1, "estimate_mode": "economical", "add_inputs": True})
+
+ self.log.info("- raises RPC error with invalid estimate_mode settings")
+ for k, v in {"number": 42, "object": {"foo": "bar"}}.items():
+ assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k),
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": v, "conf_target": 0.1, "add_inputs": True})
+ for mode in ["", "foo", Decimal("3.141592")]:
+ assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": 0.1, "add_inputs": True})
+
+ self.log.info("- raises RPC error with invalid conf_target settings")
+ for mode in ["unset", "economical", "conservative"]:
+ self.log.debug("{}".format(mode))
+ for k, v in {"string": "", "object": {"foo": "bar"}}.items():
+ assert_raises_rpc_error(-3, "Expected type number for conf_target, got {}".format(k),
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": v, "add_inputs": True})
+ for n in [-1, 0, 1009]:
+ assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h
+ self.nodes[1].walletcreatefundedpsbt, inputs, outputs, 0, {"estimate_mode": mode, "conf_target": n, "add_inputs": True})
+
+ self.log.info("Test walletcreatefundedpsbt with too-high fee rate produces total fee well above -maxtxfee and raises RPC error")
# previously this was silently capped at -maxtxfee
- assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():29.99}, 0, {"feeRate": 10, "add_inputs": True})
- assert_raises_rpc_error(-4, "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", self.nodes[1].walletcreatefundedpsbt, [{"txid":txid,"vout":p2wpkh_pos},{"txid":txid,"vout":p2sh_p2wpkh_pos},{"txid":txid,"vout":p2pkh_pos}], {self.nodes[1].getnewaddress():1}, 0, {"feeRate": 10, "add_inputs": False})
+ for bool_add, outputs_array in {True: outputs, False: [{self.nodes[1].getnewaddress(): 1}]}.items():
+ msg = "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)"
+ assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"fee_rate": 1000000, "add_inputs": bool_add})
+ assert_raises_rpc_error(-4, msg, self.nodes[1].walletcreatefundedpsbt, inputs, outputs_array, 0, {"feeRate": 1, "add_inputs": bool_add})
+ self.log.info("Test various PSBT operations")
# partially sign multisig things with node 1
psbtx = wmulti.walletcreatefundedpsbt(inputs=[{"txid":txid,"vout":p2wsh_pos},{"txid":txid,"vout":p2sh_pos},{"txid":txid,"vout":p2sh_p2wsh_pos}], outputs={self.nodes[1].getnewaddress():29.99}, options={'changeAddress': self.nodes[1].getrawchangeaddress()})['psbt']
walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx)
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index d74128b42d..60e66a27c9 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -20,7 +20,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
+ find_vout_for_address,
hex_str_to_bytes,
)
@@ -60,7 +60,7 @@ class RawTransactionsTest(BitcoinTestFramework):
def setup_network(self):
super().setup_network()
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 2)
def run_test(self):
self.log.info('prepare some coins for multiple *rawtransaction commands')
@@ -243,121 +243,124 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].reconsiderblock(block1)
assert_equal(self.nodes[0].getbestblockhash(), block2)
- #########################
- # RAW TX MULTISIG TESTS #
- #########################
- # 2of2 test
- addr1 = self.nodes[2].getnewaddress()
- addr2 = self.nodes[2].getnewaddress()
-
- addr1Obj = self.nodes[2].getaddressinfo(addr1)
- addr2Obj = self.nodes[2].getaddressinfo(addr2)
-
- # Tests for createmultisig and addmultisigaddress
- assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
- self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys
- assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here.
-
- mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']
-
- #use balance deltas instead of absolute values
- bal = self.nodes[2].getbalance()
-
- # send 1.2 BTC to msig adr
- txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
- self.sync_all()
- self.nodes[0].generate(1)
- self.sync_all()
- assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
-
-
- # 2of3 test from different nodes
- bal = self.nodes[2].getbalance()
- addr1 = self.nodes[1].getnewaddress()
- addr2 = self.nodes[2].getnewaddress()
- addr3 = self.nodes[2].getnewaddress()
-
- addr1Obj = self.nodes[1].getaddressinfo(addr1)
- addr2Obj = self.nodes[2].getaddressinfo(addr2)
- addr3Obj = self.nodes[2].getaddressinfo(addr3)
-
- mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
-
- txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
- decTx = self.nodes[0].gettransaction(txId)
- rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
- self.sync_all()
- self.nodes[0].generate(1)
- self.sync_all()
-
- #THIS IS AN INCOMPLETE FEATURE
- #NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION
- assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable
-
- txDetails = self.nodes[0].gettransaction(txId, True)
- rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
- vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('2.20000000'))
-
- bal = self.nodes[0].getbalance()
- inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}]
- outputs = { self.nodes[0].getnewaddress() : 2.19 }
- rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
- rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs)
- assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx
-
- rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx, inputs)
- assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys
- self.nodes[2].sendrawtransaction(rawTxSigned['hex'])
- rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex'])
- self.sync_all()
- self.nodes[0].generate(1)
- self.sync_all()
- assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
-
- # 2of2 test for combining transactions
- bal = self.nodes[2].getbalance()
- addr1 = self.nodes[1].getnewaddress()
- addr2 = self.nodes[2].getnewaddress()
-
- addr1Obj = self.nodes[1].getaddressinfo(addr1)
- addr2Obj = self.nodes[2].getaddressinfo(addr2)
-
- self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
- mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
- mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
-
- txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
- decTx = self.nodes[0].gettransaction(txId)
- rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
- self.sync_all()
- self.nodes[0].generate(1)
- self.sync_all()
-
- assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable
-
- txDetails = self.nodes[0].gettransaction(txId, True)
- rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
- vout = next(o for o in rawTx2['vout'] if o['value'] == Decimal('2.20000000'))
-
- bal = self.nodes[0].getbalance()
- inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}]
- outputs = { self.nodes[0].getnewaddress() : 2.19 }
- rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
- rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs)
- self.log.debug(rawTxPartialSigned1)
- assert_equal(rawTxPartialSigned1['complete'], False) #node1 only has one key, can't comp. sign the tx
-
- rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs)
- self.log.debug(rawTxPartialSigned2)
- assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx
- rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
- self.log.debug(rawTxComb)
- self.nodes[2].sendrawtransaction(rawTxComb)
- rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
- self.sync_all()
- self.nodes[0].generate(1)
- self.sync_all()
- assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
+ if not self.options.descriptors:
+ # The traditional multisig workflow does not work with descriptor wallets so these are legacy only.
+ # The multisig workflow with descriptor wallets uses PSBTs and is tested elsewhere, no need to do them here.
+ #########################
+ # RAW TX MULTISIG TESTS #
+ #########################
+ # 2of2 test
+ addr1 = self.nodes[2].getnewaddress()
+ addr2 = self.nodes[2].getnewaddress()
+
+ addr1Obj = self.nodes[2].getaddressinfo(addr1)
+ addr2Obj = self.nodes[2].getaddressinfo(addr2)
+
+ # Tests for createmultisig and addmultisigaddress
+ assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
+ self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys
+ assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here.
+
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']
+
+ #use balance deltas instead of absolute values
+ bal = self.nodes[2].getbalance()
+
+ # send 1.2 BTC to msig adr
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
+ self.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+ assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
+
+
+ # 2of3 test from different nodes
+ bal = self.nodes[2].getbalance()
+ addr1 = self.nodes[1].getnewaddress()
+ addr2 = self.nodes[2].getnewaddress()
+ addr3 = self.nodes[2].getnewaddress()
+
+ addr1Obj = self.nodes[1].getaddressinfo(addr1)
+ addr2Obj = self.nodes[2].getaddressinfo(addr2)
+ addr3Obj = self.nodes[2].getaddressinfo(addr3)
+
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
+
+ txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
+ decTx = self.nodes[0].gettransaction(txId)
+ rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
+ self.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ #THIS IS AN INCOMPLETE FEATURE
+ #NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION
+ assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable
+
+ txDetails = self.nodes[0].gettransaction(txId, True)
+ rawTx = self.nodes[0].decoderawtransaction(txDetails['hex'])
+ vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('2.20000000'))
+
+ bal = self.nodes[0].getbalance()
+ inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}]
+ outputs = { self.nodes[0].getnewaddress() : 2.19 }
+ rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
+ rawTxPartialSigned = self.nodes[1].signrawtransactionwithwallet(rawTx, inputs)
+ assert_equal(rawTxPartialSigned['complete'], False) #node1 only has one key, can't comp. sign the tx
+
+ rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx, inputs)
+ assert_equal(rawTxSigned['complete'], True) #node2 can sign the tx compl., own two of three keys
+ self.nodes[2].sendrawtransaction(rawTxSigned['hex'])
+ rawTx = self.nodes[0].decoderawtransaction(rawTxSigned['hex'])
+ self.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+ assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
+
+ # 2of2 test for combining transactions
+ bal = self.nodes[2].getbalance()
+ addr1 = self.nodes[1].getnewaddress()
+ addr2 = self.nodes[2].getnewaddress()
+
+ addr1Obj = self.nodes[1].getaddressinfo(addr1)
+ addr2Obj = self.nodes[2].getaddressinfo(addr2)
+
+ self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
+ mSigObjValid = self.nodes[2].getaddressinfo(mSigObj)
+
+ txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
+ decTx = self.nodes[0].gettransaction(txId)
+ rawTx2 = self.nodes[0].decoderawtransaction(decTx['hex'])
+ self.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ assert_equal(self.nodes[2].getbalance(), bal) # the funds of a 2of2 multisig tx should not be marked as spendable
+
+ txDetails = self.nodes[0].gettransaction(txId, True)
+ rawTx2 = self.nodes[0].decoderawtransaction(txDetails['hex'])
+ vout = next(o for o in rawTx2['vout'] if o['value'] == Decimal('2.20000000'))
+
+ bal = self.nodes[0].getbalance()
+ inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}]
+ outputs = { self.nodes[0].getnewaddress() : 2.19 }
+ rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
+ rawTxPartialSigned1 = self.nodes[1].signrawtransactionwithwallet(rawTx2, inputs)
+ self.log.debug(rawTxPartialSigned1)
+ assert_equal(rawTxPartialSigned1['complete'], False) #node1 only has one key, can't comp. sign the tx
+
+ rawTxPartialSigned2 = self.nodes[2].signrawtransactionwithwallet(rawTx2, inputs)
+ self.log.debug(rawTxPartialSigned2)
+ assert_equal(rawTxPartialSigned2['complete'], False) #node2 only has one key, can't comp. sign the tx
+ rawTxComb = self.nodes[2].combinerawtransaction([rawTxPartialSigned1['hex'], rawTxPartialSigned2['hex']])
+ self.log.debug(rawTxComb)
+ self.nodes[2].sendrawtransaction(rawTxComb)
+ rawTx2 = self.nodes[0].decoderawtransaction(rawTxComb)
+ self.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+ assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
# decoderawtransaction tests
# witness transaction
@@ -369,10 +372,28 @@ class RawTransactionsTest(BitcoinTestFramework):
encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000"
decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction
assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))
+ # known ambiguous transaction in the chain (see https://github.com/bitcoin/bitcoin/issues/20579)
+ encrawtx = "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03c68708046ff8415c622f4254432e434f4d2ffabe6d6de1965d02c68f928e5b244ab1965115a36f56eb997633c7f690124bbf43644e23080000000ca3d3af6d005a65ff0200fd00000000ffffffff03f4c1fb4b0000000016001497cfc76442fe717f2a3f0cc9c175f7561b6619970000000000000000266a24aa21a9ed957d1036a80343e0d1b659497e1b48a38ebe876a056d45965fac4a85cda84e1900000000000000002952534b424c4f434b3a8e092581ab01986cbadc84f4b43f4fa4bb9e7a2e2a0caf9b7cf64d939028e22c0120000000000000000000000000000000000000000000000000000000000000000000000000"
+ decrawtx = self.nodes[0].decoderawtransaction(encrawtx)
+ decrawtx_wit = self.nodes[0].decoderawtransaction(encrawtx, True)
+ assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # fails to decode as non-witness transaction
+ assert_equal(decrawtx, decrawtx_wit) # the witness interpretation should be chosen
+ assert_equal(decrawtx['vin'][0]['coinbase'], "03c68708046ff8415c622f4254432e434f4d2ffabe6d6de1965d02c68f928e5b244ab1965115a36f56eb997633c7f690124bbf43644e23080000000ca3d3af6d005a65ff0200fd00000000")
+
+ # Basic signrawtransaction test
+ addr = self.nodes[1].getnewaddress()
+ txid = self.nodes[0].sendtoaddress(addr, 10)
+ self.nodes[0].generate(1)
+ self.sync_all()
+ vout = find_vout_for_address(self.nodes[1], txid, addr)
+ rawTx = self.nodes[1].createrawtransaction([{'txid': txid, 'vout': vout}], {self.nodes[1].getnewaddress(): 9.999})
+ rawTxSigned = self.nodes[1].signrawtransactionwithwallet(rawTx)
+ txId = self.nodes[1].sendrawtransaction(rawTxSigned['hex'])
+ self.nodes[0].generate(1)
+ self.sync_all()
# getrawtransaction tests
# 1. valid parameters - only supply txid
- txId = rawTx["txid"]
assert_equal(self.nodes[0].getrawtransaction(txId), rawTxSigned['hex'])
# 2. valid parameters - supply txid and 0 for non-verbose
diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py
index 861b394e70..070f59d314 100755
--- a/test/functional/rpc_scantxoutset.py
+++ b/test/functional/rpc_scantxoutset.py
@@ -55,7 +55,8 @@ class ScantxoutsetTest(BitcoinTestFramework):
self.log.info("Stop node, remove wallet, mine again some blocks...")
self.stop_node(0)
shutil.rmtree(os.path.join(self.nodes[0].datadir, self.chain, 'wallets'))
- self.start_node(0)
+ self.start_node(0, ['-nowallet'])
+ self.import_deterministic_coinbase_privkeys()
self.nodes[0].generate(110)
scan = self.nodes[0].scantxoutset("start", [])
diff --git a/test/functional/rpc_setban.py b/test/functional/rpc_setban.py
index 1cc1fb164b..bc48449084 100755
--- a/test/functional/rpc_setban.py
+++ b/test/functional/rpc_setban.py
@@ -6,7 +6,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- connect_nodes,
p2p_port
)
@@ -18,7 +17,7 @@ class SetBanTests(BitcoinTestFramework):
def run_test(self):
# Node 0 connects to Node 1, check that the noban permission is not granted
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
assert(not 'noban' in peerinfo['permissions'])
@@ -32,14 +31,14 @@ class SetBanTests(BitcoinTestFramework):
# However, node 0 should be able to reconnect if it has noban permission
self.restart_node(1, ['-whitelist=127.0.0.1'])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
assert('noban' in peerinfo['permissions'])
# If we remove the ban, Node 0 should be able to reconnect even without noban permission
self.nodes[1].setban("127.0.0.1", "remove")
self.restart_node(1, [])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
assert(not 'noban' in peerinfo['permissions'])
diff --git a/test/functional/rpc_signrawtransaction.py b/test/functional/rpc_signrawtransaction.py
index 704b65c060..2fbbdbbdf0 100755
--- a/test/functional/rpc_signrawtransaction.py
+++ b/test/functional/rpc_signrawtransaction.py
@@ -5,10 +5,13 @@
"""Test transaction signing using the signrawtransaction* RPCs."""
from test_framework.address import check_script, script_to_p2sh
+from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, assert_raises_rpc_error, find_vout_for_address, hex_str_to_bytes
from test_framework.messages import sha256
from test_framework.script import CScript, OP_0, OP_CHECKSIG
+from test_framework.script_util import 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
@@ -148,24 +151,40 @@ class SignRawTransactionsTest(BitcoinTestFramework):
assert_equal(rawTxSigned['errors'][1]['witness'], ["304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee01", "025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357"])
assert not rawTxSigned['errors'][0]['witness']
+ def test_fully_signed_tx(self):
+ self.log.info("Test signing a fully signed transaction does nothing")
+ self.nodes[0].walletpassphrase("password", 9999)
+ self.nodes[0].generate(101)
+ rawtx = self.nodes[0].createrawtransaction([], [{self.nodes[0].getnewaddress(): 10}])
+ fundedtx = self.nodes[0].fundrawtransaction(rawtx)
+ signedtx = self.nodes[0].signrawtransactionwithwallet(fundedtx["hex"])
+ assert_equal(signedtx["complete"], True)
+ signedtx2 = self.nodes[0].signrawtransactionwithwallet(signedtx["hex"])
+ assert_equal(signedtx2["complete"], True)
+ 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:
- embedded_address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())
- embedded_privkey = self.nodes[1].dumpprivkey(embedded_address["address"])
- p2sh_p2wsh_address = self.nodes[1].addmultisigaddress(1, [embedded_address["pubkey"]], "", "p2sh-segwit")
+ 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.nodes[0].generate(101)
self.nodes[0].sendtoaddress(p2sh_p2wsh_address["address"], 49.999)
self.nodes[0].generate(1)
self.sync_all()
- # Find the UTXO for the transaction node[1] should have received, check witnessScript matches
- unspent_output = self.nodes[1].listunspent(0, 999999, [p2sh_p2wsh_address["address"]])[0]
- assert_equal(unspent_output["witnessScript"], p2sh_p2wsh_address["redeemScript"])
- p2sh_redeemScript = CScript([OP_0, sha256(hex_str_to_bytes(p2sh_p2wsh_address["redeemScript"]))])
- assert_equal(unspent_output["redeemScript"], p2sh_redeemScript.hex())
+ # 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].getnewaddress(): Decimal("49.998")})
+ 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
@@ -177,11 +196,13 @@ class SignRawTransactionsTest(BitcoinTestFramework):
def verify_txn_with_witness_script(self, tx_type):
self.log.info("Test with a {} script as the witnessScript".format(tx_type))
- embedded_addr_info = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress('', 'legacy'))
- embedded_privkey = self.nodes[1].dumpprivkey(embedded_addr_info['address'])
+ eckey = ECKey()
+ eckey.generate()
+ embedded_privkey = bytes_to_wif(eckey.get_bytes())
+ embedded_pubkey = eckey.get_pubkey().get_bytes().hex()
witness_script = {
- 'P2PKH': embedded_addr_info['scriptPubKey'],
- 'P2PK': CScript([hex_str_to_bytes(embedded_addr_info['pubkey']), OP_CHECKSIG]).hex()
+ 'P2PKH': key_to_p2pkh_script(embedded_pubkey).hex(),
+ 'P2PK': CScript([hex_str_to_bytes(embedded_pubkey), OP_CHECKSIG]).hex()
}.get(tx_type, "Invalid tx_type")
redeem_script = CScript([OP_0, sha256(check_script(witness_script))]).hex()
addr = script_to_p2sh(redeem_script)
@@ -223,6 +244,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
self.witness_script_test()
self.OP_1NEGATE_test()
self.test_with_lock_outputs()
+ self.test_fully_signed_tx()
if __name__ == '__main__':
diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py
index 93fb62c5d6..2d6ce77613 100755
--- a/test/functional/rpc_txoutproof.py
+++ b/test/functional/rpc_txoutproof.py
@@ -78,7 +78,7 @@ class MerkleBlockTest(BitcoinTestFramework):
# We can't get a proof if we specify transactions from different blocks
assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", self.nodes[0].gettxoutproof, [txid1, txid3])
# Test empty list
- assert_raises_rpc_error(-5, "Transaction not yet in block", self.nodes[0].gettxoutproof, [])
+ assert_raises_rpc_error(-8, "Parameter 'txids' cannot be empty", self.nodes[0].gettxoutproof, [])
# Test duplicate txid
assert_raises_rpc_error(-8, 'Invalid parameter, duplicated txid', self.nodes[0].gettxoutproof, [txid1, txid1])
diff --git a/test/functional/rpc_users.py b/test/functional/rpc_users.py
index daf02fc4f3..108af2cac8 100755
--- a/test/functional/rpc_users.py
+++ b/test/functional/rpc_users.py
@@ -99,11 +99,18 @@ class HTTPBasicsTest(BitcoinTestFramework):
self.test_auth(self.nodes[1], self.rpcuser, self.rpcpassword)
- self.log.info('Check that failure to write cookie file will abort the node gracefully')
+ init_error = 'Error: Unable to start HTTP server. See debug log for details.'
+
+ self.log.info('Check -rpcauth are validated')
+ # Empty -rpcauth= are ignored
+ self.restart_node(0, extra_args=['-rpcauth='])
self.stop_node(0)
+ self.nodes[0].assert_start_raises_init_error(expected_msg=init_error, extra_args=['-rpcauth=foo'])
+ self.nodes[0].assert_start_raises_init_error(expected_msg=init_error, extra_args=['-rpcauth=foo:bar'])
+
+ self.log.info('Check that failure to write cookie file will abort the node gracefully')
cookie_file = os.path.join(get_datadir_path(self.options.tmpdir, 0), self.chain, '.cookie.tmp')
os.mkdir(cookie_file)
- init_error = 'Error: Unable to start HTTP server. See debug log for details.'
self.nodes[0].assert_start_raises_init_error(expected_msg=init_error)
diff --git a/test/functional/test_framework/bdb.py b/test/functional/test_framework/bdb.py
new file mode 100644
index 0000000000..9de358aa0a
--- /dev/null
+++ b/test/functional/test_framework/bdb.py
@@ -0,0 +1,152 @@
+#!/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.
+"""
+Utilities for working directly with the wallet's BDB database file
+
+This is specific to the configuration of BDB used in this project:
+ - pagesize: 4096 bytes
+ - Outer database contains single subdatabase named 'main'
+ - btree
+ - btree leaf pages
+
+Each key-value pair is two entries in a btree leaf. The first is the key, the one that follows
+is the value. And so on. Note that the entry data is itself not in the correct order. Instead
+entry offsets are stored in the correct order and those offsets are needed to then retrieve
+the data itself.
+
+Page format can be found in BDB source code dbinc/db_page.h
+This only implements the deserialization of btree metadata pages and normal btree pages. Overflow
+pages are not implemented but may be needed in the future if dealing with wallets with large
+transactions.
+
+`db_dump -da wallet.dat` is useful to see the data in a wallet.dat BDB file
+"""
+
+import binascii
+import struct
+
+# Important constants
+PAGESIZE = 4096
+OUTER_META_PAGE = 0
+INNER_META_PAGE = 2
+
+# Page type values
+BTREE_INTERNAL = 3
+BTREE_LEAF = 5
+BTREE_META = 9
+
+# Some magic numbers for sanity checking
+BTREE_MAGIC = 0x053162
+DB_VERSION = 9
+
+# Deserializes a leaf page into a dict.
+# Btree internal pages have the same header, for those, return None.
+# For the btree leaf pages, deserialize them and put all the data into a dict
+def dump_leaf_page(data):
+ page_info = {}
+ page_header = data[0:26]
+ _, pgno, prev_pgno, next_pgno, entries, hf_offset, level, pg_type = struct.unpack('QIIIHHBB', page_header)
+ page_info['pgno'] = pgno
+ page_info['prev_pgno'] = prev_pgno
+ page_info['next_pgno'] = next_pgno
+ page_info['entries'] = entries
+ page_info['hf_offset'] = hf_offset
+ page_info['level'] = level
+ page_info['pg_type'] = pg_type
+ page_info['entry_offsets'] = struct.unpack('{}H'.format(entries), data[26:26 + entries * 2])
+ page_info['entries'] = []
+
+ if pg_type == BTREE_INTERNAL:
+ # Skip internal pages. These are the internal nodes of the btree and don't contain anything relevant to us
+ return None
+
+ assert pg_type == BTREE_LEAF, 'A non-btree leaf page has been encountered while dumping leaves'
+
+ for i in range(0, entries):
+ offset = page_info['entry_offsets'][i]
+ entry = {'offset': offset}
+ page_data_header = data[offset:offset + 3]
+ e_len, pg_type = struct.unpack('HB', page_data_header)
+ entry['len'] = e_len
+ entry['pg_type'] = pg_type
+ entry['data'] = data[offset + 3:offset + 3 + e_len]
+ page_info['entries'].append(entry)
+
+ return page_info
+
+# Deserializes a btree metadata page into a dict.
+# Does a simple sanity check on the magic value, type, and version
+def dump_meta_page(page):
+ # metadata page
+ # general metadata
+ metadata = {}
+ meta_page = page[0:72]
+ _, pgno, magic, version, pagesize, encrypt_alg, pg_type, metaflags, _, free, last_pgno, nparts, key_count, record_count, flags, uid = struct.unpack('QIIIIBBBBIIIIII20s', meta_page)
+ metadata['pgno'] = pgno
+ metadata['magic'] = magic
+ metadata['version'] = version
+ metadata['pagesize'] = pagesize
+ metadata['encrypt_alg'] = encrypt_alg
+ metadata['pg_type'] = pg_type
+ metadata['metaflags'] = metaflags
+ metadata['free'] = free
+ metadata['last_pgno'] = last_pgno
+ metadata['nparts'] = nparts
+ metadata['key_count'] = key_count
+ metadata['record_count'] = record_count
+ metadata['flags'] = flags
+ metadata['uid'] = binascii.hexlify(uid)
+
+ assert magic == BTREE_MAGIC, 'bdb magic does not match bdb btree magic'
+ assert pg_type == BTREE_META, 'Metadata page is not a btree metadata page'
+ assert version == DB_VERSION, 'Database too new'
+
+ # btree metadata
+ btree_meta_page = page[72:512]
+ _, minkey, re_len, re_pad, root, _, crypto_magic, _, iv, chksum = struct.unpack('IIIII368sI12s16s20s', btree_meta_page)
+ metadata['minkey'] = minkey
+ metadata['re_len'] = re_len
+ metadata['re_pad'] = re_pad
+ metadata['root'] = root
+ metadata['crypto_magic'] = crypto_magic
+ metadata['iv'] = binascii.hexlify(iv)
+ metadata['chksum'] = binascii.hexlify(chksum)
+ return metadata
+
+# Given the dict from dump_leaf_page, get the key-value pairs and put them into a dict
+def extract_kv_pairs(page_data):
+ out = {}
+ last_key = None
+ for i, entry in enumerate(page_data['entries']):
+ # By virtue of these all being pairs, even number entries are keys, and odd are values
+ if i % 2 == 0:
+ out[entry['data']] = b''
+ last_key = entry['data']
+ else:
+ out[last_key] = entry['data']
+ return out
+
+# Extract the key-value pairs of the BDB file given in filename
+def dump_bdb_kv(filename):
+ # Read in the BDB file and start deserializing it
+ pages = []
+ with open(filename, 'rb') as f:
+ data = f.read(PAGESIZE)
+ while len(data) > 0:
+ pages.append(data)
+ data = f.read(PAGESIZE)
+
+ # Sanity check the meta pages
+ dump_meta_page(pages[OUTER_META_PAGE])
+ dump_meta_page(pages[INNER_META_PAGE])
+
+ # Fetch the kv pairs from the leaf pages
+ kv = {}
+ for i in range(3, len(pages)):
+ info = dump_leaf_page(pages[i])
+ if info is not None:
+ info_kv = extract_kv_pairs(info)
+ kv = {**kv, **info_kv}
+ return kv
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index 4be8b7d80b..6b7214f03a 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -4,6 +4,9 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Utilities for manipulating blocks and transactions."""
+from binascii import a2b_hex
+import struct
+import time
import unittest
from .address import (
@@ -41,7 +44,6 @@ from .script import (
hash160,
)
from .util import assert_equal
-from io import BytesIO
WITNESS_SCALE_FACTOR = 4
MAX_BLOCK_SIGOPS = 20000
@@ -53,19 +55,29 @@ TIME_GENESIS_BLOCK = 1296688602
# From BIP141
WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
+NORMAL_GBT_REQUEST_PARAMS = {"rules": ["segwit"]}
-def create_block(hashprev, coinbase, ntime=None, *, version=1):
+
+def create_block(hashprev=None, coinbase=None, ntime=None, *, version=None, tmpl=None, txlist=None):
"""Create a block (with regtest difficulty)."""
block = CBlock()
- block.nVersion = version
- if ntime is None:
- import time
- block.nTime = int(time.time() + 600)
+ if tmpl is None:
+ tmpl = {}
+ block.nVersion = version or tmpl.get('version') or 1
+ block.nTime = ntime or tmpl.get('curtime') or int(time.time() + 600)
+ block.hashPrevBlock = hashprev or int(tmpl['previousblockhash'], 0x10)
+ if tmpl and not tmpl.get('bits') is None:
+ block.nBits = struct.unpack('>I', a2b_hex(tmpl['bits']))[0]
else:
- block.nTime = ntime
- block.hashPrevBlock = hashprev
- block.nBits = 0x207fffff # difficulty retargeting is disabled in REGTEST chainparams
+ block.nBits = 0x207fffff # difficulty retargeting is disabled in REGTEST chainparams
+ if coinbase is None:
+ coinbase = create_coinbase(height=tmpl['height'])
block.vtx.append(coinbase)
+ if txlist:
+ for tx in txlist:
+ if not hasattr(tx, 'calc_sha256'):
+ tx = FromHex(CTransaction(), tx)
+ block.vtx.append(tx)
block.hashMerkleRoot = block.calc_merkle_root()
block.calc_sha256()
return block
@@ -146,25 +158,27 @@ def create_tx_with_script(prevtx, n, script_sig=b"", *, amount, script_pub_key=C
def create_transaction(node, txid, to_address, *, amount):
""" Return signed transaction spending the first output of the
- input txid. Note that the node must be able to sign for the
- output that is being spent, and the node must not be running
- multiple wallets.
+ 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 = CTransaction()
- tx.deserialize(BytesIO(hex_str_to_bytes(raw_tx)))
+ tx = FromHex(CTransaction(), 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 be able to sign for the
- output that is being spent, and the node must not be running
- multiple wallets.
+ input txid. Note that the node must have a wallet that can sign
+ for the output that is being spent.
"""
- rawtx = node.createrawtransaction(inputs=[{"txid": txid, "vout": 0}], outputs={to_address: amount})
- signresult = node.signrawtransactionwithwallet(rawtx)
- assert_equal(signresult["complete"], True)
- return signresult['hex']
+ 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
diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py
index 17b869e542..f3d13c049b 100644
--- a/test/functional/test_framework/key.py
+++ b/test/functional/test_framework/key.py
@@ -10,7 +10,6 @@ import csv
import hashlib
import os
import random
-import sys
import unittest
from .util import modinv
@@ -22,6 +21,7 @@ def TaggedHash(tag, data):
return hashlib.sha256(ss).digest()
def xor_bytes(b0, b1):
+ assert len(b0) == len(b1)
return bytes(x ^ y for (x, y) in zip(b0, b1))
def jacobi_symbol(n, k):
@@ -240,8 +240,8 @@ class ECPubKey():
x = int.from_bytes(data[1:33], 'big')
if SECP256K1.is_x_coord(x):
p = SECP256K1.lift_x(x)
- # if the oddness of the y co-ord isn't correct, find the other
- # valid y
+ # Make the Y coordinate odd if required (lift_x always produces
+ # a point with an even Y coordinate).
if data[0] & 1:
p = SECP256K1.negate(p)
self.p = p
@@ -322,7 +322,7 @@ class ECPubKey():
u1 = z*w % SECP256K1_ORDER
u2 = r*w % SECP256K1_ORDER
R = SECP256K1.affine(SECP256K1.mul([(SECP256K1_G, u1), (self.p, u2)]))
- if R is None or R[0] != r:
+ if R is None or (R[0] % SECP256K1_ORDER) != r:
return False
return True
@@ -523,7 +523,8 @@ class TestFrameworkKey(unittest.TestCase):
def test_schnorr_testvectors(self):
"""Implement the BIP340 test vectors (read from bip340_test_vectors.csv)."""
num_tests = 0
- with open(os.path.join(sys.path[0], 'test_framework', 'bip340_test_vectors.csv'), newline='', encoding='utf8') as csvfile:
+ vectors_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bip340_test_vectors.csv')
+ with open(vectors_file, newline='', encoding='utf8') as csvfile:
reader = csv.reader(csvfile)
next(reader)
for row in reader:
@@ -542,7 +543,7 @@ class TestFrameworkKey(unittest.TestCase):
sig_actual = sign_schnorr(seckey, msg, aux_rand)
self.assertEqual(sig.hex(), sig_actual.hex(), "BIP340 test vector %i (%s): sig mismatch" % (i, comment))
except RuntimeError as e:
- self.assertFalse("BIP340 test vector %i (%s): signing raised exception %s" % (i, comment, e))
+ self.fail("BIP340 test vector %i (%s): signing raised exception %s" % (i, comment, e))
result_actual = verify_schnorr(pubkey, sig, msg)
if result:
self.assertEqual(result, result_actual, "BIP340 test vector %i (%s): verification failed" % (i, comment))
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index ff7f73bdf4..bab4ad0008 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -51,7 +51,6 @@ MAX_HEADERS_RESULTS = 2000 # Number of headers sent in one getheaders result
MAX_INV_SIZE = 50000 # Maximum number of entries in an 'inv' protocol message
NODE_NETWORK = (1 << 0)
-NODE_GETUTXO = (1 << 1)
NODE_BLOOM = (1 << 2)
NODE_WITNESS = (1 << 3)
NODE_COMPACT_FILTERS = (1 << 6)
diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py
index 6846d31221..ea769ddfa2 100755
--- a/test/functional/test_framework/p2p.py
+++ b/test/functional/test_framework/p2p.py
@@ -289,7 +289,7 @@ class P2PInterface(P2PConnection):
Individual testcases should subclass this and override the on_* methods
if they want to alter message handling behaviour."""
- def __init__(self, support_addrv2=False):
+ def __init__(self, support_addrv2=False, wtxidrelay=True):
super().__init__()
# Track number of messages of each type received.
@@ -309,6 +309,9 @@ class P2PInterface(P2PConnection):
self.support_addrv2 = support_addrv2
+ # If the peer supports wtxid-relay
+ self.wtxidrelay = wtxidrelay
+
def peer_connect(self, *args, services=NODE_NETWORK|NODE_WITNESS, send_version=True, **kwargs):
create_conn = super().peer_connect(*args, **kwargs)
@@ -394,11 +397,11 @@ class P2PInterface(P2PConnection):
def on_version(self, message):
assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED)
- if message.nVersion >= 70016:
+ if message.nVersion >= 70016 and self.wtxidrelay:
self.send_message(msg_wtxidrelay())
- self.send_message(msg_verack())
if self.support_addrv2:
self.send_message(msg_sendaddrv2())
+ self.send_message(msg_verack())
self.nServices = message.nServices
# Connection helper methods
diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py
index 8e5848d493..26ccab3039 100644
--- a/test/functional/test_framework/script.py
+++ b/test/functional/test_framework/script.py
@@ -824,21 +824,33 @@ def taproot_tree_helper(scripts):
h = TaggedHash("TapBranch", left_h + right_h)
return (left + right, h)
+# A TaprootInfo object has the following fields:
+# - scriptPubKey: the scriptPubKey (witness v1 CScript)
+# - inner_pubkey: the inner pubkey (32 bytes)
+# - negflag: whether the pubkey in the scriptPubKey was negated from inner_pubkey+tweak*G (bool).
+# - tweak: the tweak (32 bytes)
+# - leaves: a dict of name -> TaprootLeafInfo objects for all known leaves
TaprootInfo = namedtuple("TaprootInfo", "scriptPubKey,inner_pubkey,negflag,tweak,leaves")
+
+# A TaprootLeafInfo object has the following fields:
+# - script: the leaf script (CScript or bytes)
+# - version: the leaf version (0xc0 for BIP342 tapscript)
+# - merklebranch: the merkle branch to use for this leaf (32*N bytes)
TaprootLeafInfo = namedtuple("TaprootLeafInfo", "script,version,merklebranch")
def taproot_construct(pubkey, scripts=None):
"""Construct a tree of Taproot spending conditions
- pubkey: an ECPubKey object for the internal pubkey
+ pubkey: a 32-byte xonly pubkey for the internal pubkey (bytes)
scripts: a list of items; each item is either:
- - a (name, CScript) tuple
- - a (name, CScript, leaf version) tuple
+ - a (name, CScript or bytes, leaf version) tuple
+ - a (name, CScript or bytes) tuple (defaulting to leaf version 0xc0)
- another list of items (with the same structure)
- - a function, which specifies how to compute the hashing partner
- in function of the hash of whatever it is combined with
+ - a list of two items; the first of which is an item itself, and the
+ second is a function. The function takes as input the Merkle root of the
+ first item, and produces a (fictitious) partner to hash with.
- Returns: script (sPK or redeemScript), tweak, {name:(script, leaf version, negation flag, innerkey, merklepath), ...}
+ Returns: a TaprootInfo object
"""
if scripts is None:
scripts = []
diff --git a/test/functional/test_framework/script_util.py b/test/functional/test_framework/script_util.py
index 80fbae70bf..318a438705 100755
--- a/test/functional/test_framework/script_util.py
+++ b/test/functional/test_framework/script_util.py
@@ -3,7 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Useful Script constants and utils."""
-from test_framework.script import CScript
+from test_framework.script import CScript, hash160, sha256, OP_0, OP_DUP, OP_HASH160, OP_CHECKSIG, OP_EQUAL, OP_EQUALVERIFY
+from test_framework.util import hex_str_to_bytes
# To prevent a "tx-size-small" policy rule error, a transaction has to have a
# non-witness size of at least 82 bytes (MIN_STANDARD_TX_NONWITNESS_SIZE in
@@ -24,3 +25,59 @@ from test_framework.script import CScript
# met.
DUMMY_P2WPKH_SCRIPT = CScript([b'a' * 21])
DUMMY_2_P2WPKH_SCRIPT = CScript([b'b' * 21])
+
+def keyhash_to_p2pkh_script(hash, main = False):
+ assert len(hash) == 20
+ return CScript([OP_DUP, OP_HASH160, hash, OP_EQUALVERIFY, OP_CHECKSIG])
+
+def scripthash_to_p2sh_script(hash, main = False):
+ assert len(hash) == 20
+ return CScript([OP_HASH160, hash, OP_EQUAL])
+
+def key_to_p2pkh_script(key, main = False):
+ key = check_key(key)
+ return keyhash_to_p2pkh_script(hash160(key), main)
+
+def script_to_p2sh_script(script, main = False):
+ script = check_script(script)
+ return scripthash_to_p2sh_script(hash160(script), main)
+
+def key_to_p2sh_p2wpkh_script(key, main = False):
+ key = check_key(key)
+ p2shscript = CScript([OP_0, hash160(key)])
+ return script_to_p2sh_script(p2shscript, main)
+
+def program_to_witness_script(version, program, main = False):
+ if isinstance(program, str):
+ program = hex_str_to_bytes(program)
+ assert 0 <= version <= 16
+ assert 2 <= len(program) <= 40
+ assert version > 0 or len(program) in [20, 32]
+ return CScript([version, program])
+
+def script_to_p2wsh_script(script, main = False):
+ script = check_script(script)
+ return program_to_witness_script(0, sha256(script), main)
+
+def key_to_p2wpkh_script(key, main = False):
+ key = check_key(key)
+ return program_to_witness_script(0, hash160(key), main)
+
+def script_to_p2sh_p2wsh_script(script, main = False):
+ script = check_script(script)
+ p2shscript = CScript([OP_0, sha256(script)])
+ return script_to_p2sh_script(p2shscript, main)
+
+def check_key(key):
+ if isinstance(key, str):
+ key = hex_str_to_bytes(key) # Assuming this is hex string
+ if isinstance(key, bytes) and (len(key) == 33 or len(key) == 65):
+ return key
+ assert False
+
+def check_script(script):
+ if isinstance(script, str):
+ script = hex_str_to_bytes(script) # Assuming this is hex string
+ if isinstance(script, bytes) or isinstance(script, CScript):
+ return script
+ assert False
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 115ffa3e8d..bf047c5f68 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -27,10 +27,9 @@ from .util import (
PortSeed,
assert_equal,
check_json_precision,
- connect_nodes,
- disconnect_nodes,
get_datadir_path,
initialize_datadir,
+ p2p_port,
wait_until_helper,
)
@@ -112,6 +111,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# are not imported.
self.wallet_names = None
self.set_test_params()
+ assert self.wallet_names is None or len(self.wallet_names) <= self.num_nodes
if self.options.timeout_factor == 0 :
self.options.timeout_factor = 99999
self.rpc_timeout = int(self.rpc_timeout * self.options.timeout_factor) # optionally, increase timeout by a factor
@@ -183,9 +183,14 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
help="run nodes under the valgrind memory error detector: expect at least a ~10x slowdown, valgrind 3.14 or later required")
parser.add_argument("--randomseed", type=int,
help="set a random seed for deterministically reproducing a previous test run")
- parser.add_argument("--descriptors", default=False, action="store_true",
- help="Run test using a descriptor wallet")
parser.add_argument('--timeout-factor', dest="timeout_factor", type=float, default=1.0, help='adjust test timeouts by a factor. Setting it to 0 disables all timeouts')
+
+ group = parser.add_mutually_exclusive_group()
+ group.add_argument("--descriptors", default=False, action="store_true",
+ help="Run test using a descriptor wallet", dest='descriptors')
+ group.add_argument("--legacy-wallet", default=False, action="store_false",
+ help="Run test using legacy wallets", dest='descriptors')
+
self.add_options(parser)
self.options = parser.parse_args()
self.options.previous_releases_path = previous_releases_path
@@ -391,9 +396,13 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
assert_equal(chain_info["initialblockdownload"], False)
def import_deterministic_coinbase_privkeys(self):
- wallet_names = [self.default_wallet_name] * len(self.nodes) if self.wallet_names is None else self.wallet_names
- assert len(wallet_names) <= len(self.nodes)
- for wallet_name, n in zip(wallet_names, self.nodes):
+ for i in range(self.num_nodes):
+ self.init_wallet(i)
+
+ def init_wallet(self, i):
+ wallet_name = self.default_wallet_name if self.wallet_names is None else self.wallet_names[i] if i < len(self.wallet_names) else False
+ if wallet_name is not False:
+ n = self.nodes[i]
if wallet_name is not None:
n.createwallet(wallet_name=wallet_name, descriptors=self.options.descriptors, load_on_startup=True)
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase')
@@ -529,10 +538,49 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.nodes[i].process.wait(timeout)
def connect_nodes(self, a, b):
- connect_nodes(self.nodes[a], b)
+ def connect_nodes_helper(from_connection, node_num):
+ ip_port = "127.0.0.1:" + str(p2p_port(node_num))
+ from_connection.addnode(ip_port, "onetry")
+ # poll until version handshake complete to avoid race conditions
+ # with transaction relaying
+ # 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['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in from_connection.getpeerinfo()))
+
+ connect_nodes_helper(self.nodes[a], b)
def disconnect_nodes(self, a, b):
- disconnect_nodes(self.nodes[a], b)
+ def disconnect_nodes_helper(from_connection, node_num):
+ def get_peer_ids():
+ 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()
+ if not peer_ids:
+ self.log.warning("disconnect_nodes: {} and {} were not connected".format(
+ from_connection.index,
+ node_num,
+ ))
+ return
+ for peer_id in peer_ids:
+ try:
+ from_connection.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.
+ # This avoids a race condition if we're mass-disconnecting peers.
+ if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED
+ raise
+
+ # wait to disconnect
+ wait_until_helper(lambda: not get_peer_ids(), timeout=5)
+
+ disconnect_nodes_helper(self.nodes[a], b)
def split_network(self):
"""
@@ -726,6 +774,18 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
"""Skip the running test if wallet has not been compiled."""
if not self.is_wallet_compiled():
raise SkipTest("wallet has not been compiled.")
+ if self.options.descriptors:
+ self.skip_if_no_sqlite()
+
+ def skip_if_no_sqlite(self):
+ """Skip the running test if sqlite has not been compiled."""
+ if not self.is_sqlite_compiled():
+ raise SkipTest("sqlite has not been compiled.")
+
+ def skip_if_no_bdb(self):
+ """Skip the running test if BDB has not been compiled."""
+ if not self.is_bdb_compiled():
+ raise SkipTest("BDB has not been compiled.")
def skip_if_no_wallet_tool(self):
"""Skip the running test if bitcoin-wallet has not been compiled."""
@@ -765,3 +825,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
def is_zmq_compiled(self):
"""Checks whether the zmq module was compiled."""
return self.config["components"].getboolean("ENABLE_ZMQ")
+
+ def is_sqlite_compiled(self):
+ """Checks whether the wallet module was compiled with Sqlite support."""
+ return self.config["components"].getboolean("USE_SQLITE")
+
+ def is_bdb_compiled(self):
+ """Checks whether the wallet module was compiled with BDB support."""
+ return self.config["components"].getboolean("USE_BDB")
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 046efe730e..a618706a77 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -482,11 +482,8 @@ class TestNode():
tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False) as log_stdout:
try:
self.start(extra_args, stdout=log_stdout, stderr=log_stderr, *args, **kwargs)
- self.wait_for_rpc_connection()
- self.stop_node()
- self.wait_until_stopped()
- except FailedToStartError as e:
- self.log.debug('bitcoind failed to start: %s', e)
+ ret = self.process.wait(timeout=self.rpc_timeout)
+ self.log.debug(self._node_msg(f'bitcoind exited with status {ret} during initialization'))
self.running = False
self.process = None
# Check stderr for expected message
@@ -505,11 +502,15 @@ class TestNode():
if expected_msg != stderr:
self._raise_assertion_error(
'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr))
- else:
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.running = False
+ self.process = None
+ assert_msg = f'bitcoind should have exited within {self.rpc_timeout}s '
if expected_msg is None:
- assert_msg = "bitcoind should have exited with an error"
+ assert_msg += "with an error"
else:
- assert_msg = "bitcoind should have exited with expected error " + expected_msg
+ assert_msg += "with expected error " + expected_msg
self._raise_assertion_error(assert_msg)
def add_p2p_connection(self, p2p_conn, *, wait_for_verack=True, **kwargs):
@@ -544,7 +545,7 @@ class TestNode():
def num_test_p2p_connections(self):
"""Return number of test framework p2p connections to the node."""
- return len([peer for peer in self.getpeerinfo() if peer['subver'] == MY_SUBVERSION])
+ return len([peer for peer in self.getpeerinfo() if peer['subver'] == MY_SUBVERSION.decode("utf-8")])
def disconnect_p2ps(self):
"""Close all p2p connections to the node."""
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index af7f0b62f4..62ff5c6e33 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -8,11 +8,11 @@ from base64 import b64encode
from binascii import unhexlify
from decimal import Decimal, ROUND_DOWN
from subprocess import CalledProcessError
+import hashlib
import inspect
import json
import logging
import os
-import random
import re
import time
import unittest
@@ -261,6 +261,14 @@ def wait_until_helper(predicate, *, attempts=float('inf'), timeout=float('inf'),
raise AssertionError("Predicate {} not true after {} seconds".format(predicate_source, timeout))
raise RuntimeError('Unreachable')
+def sha256sum_file(filename):
+ h = hashlib.sha256()
+ with open(filename, 'rb') as f:
+ d = f.read(4096)
+ while len(d) > 0:
+ h.update(d)
+ d = f.read(4096)
+ return h.digest()
# RPC/P2P connection constants and functions
############################################
@@ -412,47 +420,6 @@ def set_node_times(nodes, t):
node.setmocktime(t)
-def disconnect_nodes(from_connection, node_num):
- def get_peer_ids():
- 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()
- if not peer_ids:
- logger.warning("disconnect_nodes: {} and {} were not connected".format(
- from_connection.index,
- node_num,
- ))
- return
- for peer_id in peer_ids:
- try:
- from_connection.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.
- # This avoids a race condition if we're mass-disconnecting peers.
- if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED
- raise
-
- # wait to disconnect
- wait_until_helper(lambda: not get_peer_ids(), timeout=5)
-
-
-def connect_nodes(from_connection, node_num):
- ip_port = "127.0.0.1:" + str(p2p_port(node_num))
- from_connection.addnode(ip_port, "onetry")
- # poll until version handshake complete to avoid race conditions
- # with transaction relaying
- # 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['bytesrecv_per_msg'].pop('verack', 0) == 24 for peer in from_connection.getpeerinfo()))
-
-
# Transaction/Block functions
#############################
@@ -469,62 +436,6 @@ def find_output(node, txid, amount, *, blockhash=None):
raise RuntimeError("find_output txid %s : %s not found" % (txid, str(amount)))
-def gather_inputs(from_node, amount_needed, confirmations_required=1):
- """
- Return a random set of unspent txouts that are enough to pay amount_needed
- """
- assert confirmations_required >= 0
- utxo = from_node.listunspent(confirmations_required)
- random.shuffle(utxo)
- inputs = []
- total_in = Decimal("0.00000000")
- while total_in < amount_needed and len(utxo) > 0:
- t = utxo.pop()
- total_in += t["amount"]
- inputs.append({"txid": t["txid"], "vout": t["vout"], "address": t["address"]})
- if total_in < amount_needed:
- raise RuntimeError("Insufficient funds: need %d, have %d" % (amount_needed, total_in))
- return (total_in, inputs)
-
-
-def make_change(from_node, amount_in, amount_out, fee):
- """
- Create change output(s), return them
- """
- outputs = {}
- amount = amount_out + fee
- change = amount_in - amount
- if change > amount * 2:
- # Create an extra change output to break up big inputs
- change_address = from_node.getnewaddress()
- # Split change in two, being careful of rounding:
- outputs[change_address] = Decimal(change / 2).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
- change = amount_in - amount - outputs[change_address]
- if change > 0:
- outputs[from_node.getnewaddress()] = change
- return outputs
-
-
-def random_transaction(nodes, amount, min_fee, fee_increment, fee_variants):
- """
- Create a random transaction.
- Returns (txid, hex-encoded-transaction-data, fee)
- """
- from_node = random.choice(nodes)
- to_node = random.choice(nodes)
- fee = min_fee + fee_increment * random.randint(0, fee_variants)
-
- (total_in, inputs) = gather_inputs(from_node, amount + fee)
- outputs = make_change(from_node, total_in, amount, fee)
- outputs[to_node.getnewaddress()] = float(amount)
-
- rawtx = from_node.createrawtransaction(inputs, outputs)
- signresult = from_node.signrawtransactionwithwallet(rawtx)
- txid = from_node.sendrawtransaction(signresult["hex"], 0)
-
- return (txid, signresult["hex"], fee)
-
-
# Helper to create at least "count" utxos
# Pass in a fee that is sufficient for relay and mining new transactions.
def create_confirmed_utxos(fee, node, count):
diff --git a/test/functional/test_framework/wallet.py b/test/functional/test_framework/wallet.py
index 39b3bf2a5b..a71f2c69cb 100644
--- a/test/functional/test_framework/wallet.py
+++ b/test/functional/test_framework/wallet.py
@@ -40,9 +40,20 @@ class MiniWallet:
self._utxos.append({'txid': cb_tx['txid'], 'vout': 0, 'value': cb_tx['vout'][0]['value']})
return blocks
- def get_utxo(self):
- """Return the last utxo. Can be used to get the change output immediately after a send_self_transfer"""
- return self._utxos.pop()
+ def get_utxo(self, *, txid=''):
+ """
+ Returns a utxo and marks it as spent (pops it from the internal list)
+
+ Args:
+ txid (string), optional: get the first utxo we find from a specific transaction
+
+ Note: Can be used to get the change output immediately after a send_self_transfer
+ """
+ index = -1 # by default the last utxo
+ if txid:
+ utxo = next(filter(lambda utxo: txid == utxo['txid'], self._utxos))
+ index = self._utxos.index(utxo)
+ return self._utxos.pop(index)
def send_self_transfer(self, *, fee_rate=Decimal("0.003"), from_node, utxo_to_spend=None):
"""Create and send a tx with the specified fee_rate. Fee may be exact or at most one satoshi higher than needed."""
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 8cd82649b6..5b3db282e1 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -95,8 +95,9 @@ BASE_SCRIPTS = [
'feature_maxuploadtarget.py',
'feature_block.py',
'rpc_fundrawtransaction.py',
+ 'rpc_fundrawtransaction.py --descriptors',
'p2p_compactblocks.py',
- 'feature_segwit.py',
+ 'feature_segwit.py --legacy-wallet',
# vv Tests less than 2m vv
'wallet_basic.py',
'wallet_basic.py --descriptors',
@@ -106,19 +107,24 @@ BASE_SCRIPTS = [
'p2p_timeouts.py',
'p2p_tx_download.py',
'mempool_updatefromblock.py',
- 'wallet_dump.py',
+ 'wallet_dump.py --legacy-wallet',
'wallet_listtransactions.py',
+ 'wallet_listtransactions.py --descriptors',
'feature_taproot.py',
# vv Tests less than 60s vv
'p2p_sendheaders.py',
- 'wallet_importmulti.py',
+ 'wallet_importmulti.py --legacy-wallet',
'mempool_limit.py',
'rpc_txoutproof.py',
'wallet_listreceivedby.py',
+ 'wallet_listreceivedby.py --descriptors',
'wallet_abandonconflict.py',
+ 'wallet_abandonconflict.py --descriptors',
'feature_csv_activation.py',
'rpc_rawtransaction.py',
+ 'rpc_rawtransaction.py --descriptors',
'wallet_address_types.py',
+ 'wallet_address_types.py --descriptors',
'feature_bip68_sequence.py',
'p2p_feefilter.py',
'feature_reindex.py',
@@ -132,6 +138,7 @@ BASE_SCRIPTS = [
'mempool_resurrect.py',
'wallet_txn_doublespend.py --mineblock',
'tool_wallet.py',
+ 'tool_wallet.py --descriptors',
'wallet_txn_clone.py',
'wallet_txn_clone.py --segwit',
'rpc_getchaintips.py',
@@ -147,8 +154,9 @@ BASE_SCRIPTS = [
'wallet_multiwallet.py --usecli',
'wallet_createwallet.py',
'wallet_createwallet.py --usecli',
- 'wallet_watchonly.py',
- 'wallet_watchonly.py --usecli',
+ 'wallet_createwallet.py --descriptors',
+ 'wallet_watchonly.py --legacy-wallet',
+ 'wallet_watchonly.py --usecli --legacy-wallet',
'wallet_reorgsrestore.py',
'interface_http.py',
'interface_rpc.py',
@@ -158,20 +166,23 @@ BASE_SCRIPTS = [
'rpc_whitelist.py',
'feature_proxy.py',
'rpc_signrawtransaction.py',
+ 'rpc_signrawtransaction.py --descriptors',
'wallet_groups.py',
'p2p_addrv2_relay.py',
+ 'wallet_groups.py --descriptors',
'p2p_disconnect_ban.py',
'rpc_decodescript.py',
'rpc_blockchain.py',
'rpc_deprecated.py',
'wallet_disable.py',
+ 'wallet_disable.py --descriptors',
'p2p_addr_relay.py',
'p2p_getaddr_caching.py',
'p2p_getdata.py',
'rpc_net.py',
'wallet_keypool.py',
'wallet_keypool.py --descriptors',
- 'wallet_descriptor.py',
+ 'wallet_descriptor.py --descriptors',
'p2p_nobloomfilter_messages.py',
'p2p_filter.py',
'rpc_setban.py',
@@ -184,7 +195,9 @@ BASE_SCRIPTS = [
'feature_assumevalid.py',
'example_test.py',
'wallet_txn_doublespend.py',
+ 'wallet_txn_doublespend.py --descriptors',
'feature_backwards_compatibility.py',
+ 'feature_backwards_compatibility.py --descriptors',
'wallet_txn_clone.py --mineblock',
'feature_notifications.py',
'rpc_getblockfilter.py',
@@ -197,18 +210,21 @@ BASE_SCRIPTS = [
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
'wallet_importprunedfunds.py',
+ 'wallet_importprunedfunds.py --descriptors',
'p2p_leak_tx.py',
'p2p_eviction.py',
'rpc_signmessage.py',
'rpc_generateblock.py',
'rpc_generate.py',
'wallet_balance.py',
+ 'wallet_balance.py --descriptors',
'feature_nulldummy.py',
+ 'feature_nulldummy.py --descriptors',
'mempool_accept.py',
'mempool_expiry.py',
- 'wallet_import_rescan.py',
- 'wallet_import_with_label.py',
- 'wallet_importdescriptors.py',
+ 'wallet_import_rescan.py --legacy-wallet',
+ 'wallet_import_with_label.py --legacy-wallet',
+ 'wallet_importdescriptors.py --descriptors',
'wallet_upgradewallet.py',
'rpc_bind.py --ipv4',
'rpc_bind.py --ipv6',
@@ -216,9 +232,11 @@ BASE_SCRIPTS = [
'mining_basic.py',
'feature_signet.py',
'wallet_bumpfee.py',
- 'wallet_implicitsegwit.py',
+ 'wallet_bumpfee.py --descriptors',
+ 'wallet_implicitsegwit.py --legacy-wallet',
'rpc_named_arguments.py',
'wallet_listsinceblock.py',
+ 'wallet_listsinceblock.py --descriptors',
'p2p_leak.py',
'wallet_encryption.py',
'wallet_encryption.py --descriptors',
@@ -226,16 +244,20 @@ BASE_SCRIPTS = [
'feature_cltv.py',
'rpc_uptime.py',
'wallet_resendwallettransactions.py',
+ 'wallet_resendwallettransactions.py --descriptors',
'wallet_fallbackfee.py',
+ 'wallet_fallbackfee.py --descriptors',
'rpc_dumptxoutset.py',
'feature_minchainwork.py',
'rpc_estimatefee.py',
'rpc_getblockstats.py',
'wallet_create_tx.py',
'wallet_send.py',
+ 'wallet_create_tx.py --descriptors',
'p2p_fingerprint.py',
'feature_uacomment.py',
'wallet_coinbase_category.py',
+ 'wallet_coinbase_category.py --descriptors',
'feature_filelock.py',
'feature_loadblock.py',
'p2p_dos_header_tree.py',
diff --git a/test/functional/tool_wallet.py b/test/functional/tool_wallet.py
index 3f25c58851..35576f00ea 100755
--- a/test/functional/tool_wallet.py
+++ b/test/functional/tool_wallet.py
@@ -28,8 +28,11 @@ class ToolWalletTest(BitcoinTestFramework):
def bitcoin_wallet_process(self, *args):
binary = self.config["environment"]["BUILDDIR"] + '/src/bitcoin-wallet' + self.config["environment"]["EXEEXT"]
- args = ['-datadir={}'.format(self.nodes[0].datadir), '-chain=%s' % self.chain] + list(args)
- return subprocess.Popen([binary] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+ default_args = ['-datadir={}'.format(self.nodes[0].datadir), '-chain=%s' % self.chain]
+ if self.options.descriptors:
+ default_args.append('-descriptors')
+
+ return subprocess.Popen([binary] + default_args + list(args), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
def assert_raises_tool_error(self, error, *args):
p = self.bitcoin_wallet_process(*args)
@@ -63,6 +66,36 @@ 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):
+ wallet_name = self.default_wallet_name if name == "" else name
+ output_types = 3 # p2pkh, p2sh, segwit
+ if self.options.descriptors:
+ return textwrap.dedent('''\
+ Wallet info
+ ===========
+ Name: %s
+ Format: sqlite
+ Descriptors: yes
+ Encrypted: no
+ HD (hd seed available): yes
+ Keypool Size: %d
+ Transactions: %d
+ Address Book: %d
+ ''' % (wallet_name, keypool * output_types, transactions, address))
+ else:
+ return textwrap.dedent('''\
+ Wallet info
+ ===========
+ Name: %s
+ Format: bdb
+ Descriptors: no
+ Encrypted: no
+ HD (hd seed available): yes
+ Keypool Size: %d
+ Transactions: %d
+ Address Book: %d
+ ''' % (wallet_name, keypool, transactions, address * output_types))
+
def test_invalid_tool_commands_and_args(self):
self.log.info('Testing that various invalid commands raise with specific error messages')
self.assert_raises_tool_error('Invalid command: foo', 'foo')
@@ -71,8 +104,11 @@ class ToolWalletTest(BitcoinTestFramework):
self.assert_raises_tool_error('Error: two methods provided (info and create). Only one method should be provided.', 'info', 'create')
self.assert_raises_tool_error('Error parsing command line arguments: Invalid parameter -foo', '-foo')
locked_dir = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets")
+ error = 'Error initializing wallet database environment "{}"!'.format(locked_dir)
+ if self.options.descriptors:
+ error = "SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another bitcoind?"
self.assert_raises_tool_error(
- 'Error initializing wallet database environment "{}"!'.format(locked_dir),
+ error,
'-wallet=' + self.default_wallet_name,
'info',
)
@@ -95,15 +131,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 = textwrap.dedent('''\
- Wallet info
- ===========
- Encrypted: no
- HD (hd seed available): yes
- Keypool Size: 2
- Transactions: 0
- Address Book: 3
- ''')
+ out = self.get_expected_info_output(address=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))
@@ -134,15 +162,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 = textwrap.dedent('''\
- Wallet info
- ===========
- Encrypted: no
- HD (hd seed available): yes
- Keypool Size: 2
- Transactions: 1
- Address Book: 3
- ''')
+ out = self.get_expected_info_output(transactions=1, address=1)
self.assert_tool_output(out, '-wallet=' + self.default_wallet_name, 'info')
shasum_after = self.wallet_shasum()
timestamp_after = self.wallet_timestamp()
@@ -160,16 +180,7 @@ class ToolWalletTest(BitcoinTestFramework):
shasum_before = self.wallet_shasum()
timestamp_before = self.wallet_timestamp()
self.log.debug('Wallet file timestamp before calling create: {}'.format(timestamp_before))
- out = textwrap.dedent('''\
- Topping up keypool...
- Wallet info
- ===========
- Encrypted: no
- HD (hd seed available): yes
- Keypool Size: 2000
- Transactions: 0
- Address Book: 0
- ''')
+ out = "Topping up keypool...\n" + self.get_expected_info_output(name="foo", keypool=2000)
self.assert_tool_output(out, '-wallet=foo', 'create')
shasum_after = self.wallet_shasum()
timestamp_after = self.wallet_timestamp()
@@ -195,9 +206,13 @@ class ToolWalletTest(BitcoinTestFramework):
self.log.debug('Wallet file timestamp after calling getwalletinfo: {}'.format(timestamp_after))
assert_equal(0, out['txcount'])
- assert_equal(1000, out['keypoolsize'])
- assert_equal(1000, out['keypoolsize_hd_internal'])
- assert_equal(True, 'hdseedid' in out)
+ if not self.options.descriptors:
+ assert_equal(1000, out['keypoolsize'])
+ assert_equal(1000, out['keypoolsize_hd_internal'])
+ assert_equal(True, 'hdseedid' in out)
+ else:
+ assert_equal(3000, out['keypoolsize'])
+ assert_equal(3000, out['keypoolsize_hd_internal'])
self.log_wallet_timestamp_comparison(timestamp_before, timestamp_after)
assert_equal(timestamp_before, timestamp_after)
@@ -207,7 +222,8 @@ class ToolWalletTest(BitcoinTestFramework):
def test_salvage(self):
# TODO: Check salvage actually salvages and doesn't break things. https://github.com/bitcoin/bitcoin/issues/7463
self.log.info('Check salvage')
- self.start_node(0, ['-wallet=salvage'])
+ self.start_node(0)
+ self.nodes[0].createwallet("salvage")
self.stop_node(0)
self.assert_tool_output('', '-wallet=salvage', 'salvage')
@@ -220,7 +236,9 @@ class ToolWalletTest(BitcoinTestFramework):
self.test_tool_wallet_info_after_transaction()
self.test_tool_wallet_create_on_existing_wallet()
self.test_getwalletinfo_on_different_wallet()
- self.test_salvage()
+ if not self.options.descriptors:
+ # Salvage is a legacy wallet only thing
+ self.test_salvage()
if __name__ == '__main__':
ToolWalletTest().main()
diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py
index 8837e13005..2e0edcfa38 100755
--- a/test/functional/wallet_abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -16,8 +16,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
- disconnect_nodes,
)
@@ -50,7 +48,7 @@ class AbandonConflictTest(BitcoinTestFramework):
balance = newbalance
# Disconnect nodes so node0's transactions don't get into node1's mempool
- disconnect_nodes(self.nodes[0], 1)
+ self.disconnect_nodes(0, 1)
# Identify the 10btc outputs
nA = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txA)["details"] if tx_out["amount"] == Decimal("10"))
@@ -161,7 +159,7 @@ class AbandonConflictTest(BitcoinTestFramework):
self.nodes[1].sendrawtransaction(signed["hex"])
self.nodes[1].generate(1)
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks()
# Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index bba0b8974d..2db5eae33b 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -62,7 +62,6 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_raises_rpc_error,
- connect_nodes,
)
class AddressTypeTest(BitcoinTestFramework):
@@ -90,7 +89,7 @@ class AddressTypeTest(BitcoinTestFramework):
# Fully mesh-connect nodes for faster mempool sync
for i, j in itertools.product(range(self.num_nodes), repeat=2):
if i > j:
- connect_nodes(self.nodes[i], j)
+ self.connect_nodes(i, j)
self.sync_all()
def get_balances(self, key='trusted'):
@@ -229,18 +228,25 @@ class AddressTypeTest(BitcoinTestFramework):
compressed_1 = "0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"
compressed_2 = "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073"
- # addmultisigaddress with at least 1 uncompressed key should return a legacy address.
- for node in range(4):
- self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy')
- self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], True, 'legacy')
- self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], True, 'legacy')
- # addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours).
- self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'legacy')
- self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
- self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
- self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'bech32')
-
- for explicit_type, multisig, from_node in itertools.product([False, True], [False, True], range(4)):
+ if not self.options.descriptors:
+ # Tests for addmultisigaddress's address type behavior is only for legacy wallets.
+ # Descriptor wallets do not have addmultsigaddress so these tests are not needed for those.
+ # addmultisigaddress with at least 1 uncompressed key should return a legacy address.
+ for node in range(4):
+ self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy')
+ self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], True, 'legacy')
+ self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], True, 'legacy')
+ # addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours).
+ self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'legacy')
+ self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
+ self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
+ self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'bech32')
+
+ do_multisigs = [False]
+ if not self.options.descriptors:
+ do_multisigs.append(True)
+
+ for explicit_type, multisig, from_node in itertools.product([False, True], do_multisigs, range(4)):
address_type = None
if explicit_type and not multisig:
if from_node == 1:
diff --git a/test/functional/wallet_avoidreuse.py b/test/functional/wallet_avoidreuse.py
index eddd938847..229c134a4b 100755
--- a/test/functional/wallet_avoidreuse.py
+++ b/test/functional/wallet_avoidreuse.py
@@ -9,7 +9,6 @@ from test_framework.util import (
assert_approx,
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
)
def reset_balance(node, discardaddr):
@@ -111,7 +110,7 @@ class AvoidReuseTest(BitcoinTestFramework):
assert_equal(self.nodes[1].getwalletinfo()["avoid_reuse"], True)
self.restart_node(1)
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
# Flags should still be node1.avoid_reuse=false, node2.avoid_reuse=true
assert_equal(self.nodes[0].getwalletinfo()["avoid_reuse"], False)
diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py
index 0cf8e6d926..f34c1345e0 100755
--- a/test/functional/wallet_backup.py
+++ b/test/functional/wallet_backup.py
@@ -39,7 +39,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
)
@@ -62,10 +61,10 @@ class WalletBackupTest(BitcoinTestFramework):
def setup_network(self):
self.setup_nodes()
- connect_nodes(self.nodes[0], 3)
- connect_nodes(self.nodes[1], 3)
- connect_nodes(self.nodes[2], 3)
- connect_nodes(self.nodes[2], 0)
+ self.connect_nodes(0, 3)
+ self.connect_nodes(1, 3)
+ self.connect_nodes(2, 3)
+ self.connect_nodes(2, 0)
self.sync_all()
def one_send(self, from_node, to_address):
@@ -92,14 +91,14 @@ class WalletBackupTest(BitcoinTestFramework):
self.sync_blocks()
# As above, this mirrors the original bash test.
- def start_three(self):
- self.start_node(0)
- self.start_node(1)
- self.start_node(2)
- connect_nodes(self.nodes[0], 3)
- connect_nodes(self.nodes[1], 3)
- connect_nodes(self.nodes[2], 3)
- connect_nodes(self.nodes[2], 0)
+ def start_three(self, args=()):
+ self.start_node(0, self.extra_args[0] + list(args))
+ self.start_node(1, self.extra_args[1] + list(args))
+ self.start_node(2, self.extra_args[2] + list(args))
+ self.connect_nodes(0, 3)
+ self.connect_nodes(1, 3)
+ self.connect_nodes(2, 3)
+ self.connect_nodes(2, 0)
def stop_three(self):
self.stop_node(0)
@@ -111,6 +110,11 @@ class WalletBackupTest(BitcoinTestFramework):
os.remove(os.path.join(self.nodes[1].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
os.remove(os.path.join(self.nodes[2].datadir, self.chain, 'wallets', self.default_wallet_name, self.wallet_data_filename))
+ def init_three(self):
+ self.init_wallet(0)
+ self.init_wallet(1)
+ self.init_wallet(2)
+
def run_test(self):
self.log.info("Generating initial blockchain")
self.nodes[0].generate(1)
@@ -194,7 +198,8 @@ class WalletBackupTest(BitcoinTestFramework):
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'blocks'))
shutil.rmtree(os.path.join(self.nodes[2].datadir, self.chain, 'chainstate'))
- self.start_three()
+ self.start_three(["-nowallet"])
+ self.init_three()
assert_equal(self.nodes[0].getbalance(), 0)
assert_equal(self.nodes[1].getbalance(), 0)
diff --git a/test/functional/wallet_balance.py b/test/functional/wallet_balance.py
index e4989b4fea..433b40faee 100755
--- a/test/functional/wallet_balance.py
+++ b/test/functional/wallet_balance.py
@@ -11,7 +11,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
)
@@ -58,14 +57,16 @@ class WalletTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def run_test(self):
- self.nodes[0].importaddress(ADDRESS_WATCHONLY)
- # Check that nodes don't own any UTXOs
- assert_equal(len(self.nodes[0].listunspent()), 0)
- assert_equal(len(self.nodes[1].listunspent()), 0)
+ if not self.options.descriptors:
+ # Tests legacy watchonly behavior which is not present (and does not need to be tested) in descriptor wallets
+ self.nodes[0].importaddress(ADDRESS_WATCHONLY)
+ # Check that nodes don't own any UTXOs
+ assert_equal(len(self.nodes[0].listunspent()), 0)
+ assert_equal(len(self.nodes[1].listunspent()), 0)
- self.log.info("Check that only node 0 is watching an address")
- assert 'watchonly' in self.nodes[0].getbalances()
- assert 'watchonly' not in self.nodes[1].getbalances()
+ self.log.info("Check that only node 0 is watching an address")
+ assert 'watchonly' in self.nodes[0].getbalances()
+ assert 'watchonly' not in self.nodes[1].getbalances()
self.log.info("Mining blocks ...")
self.nodes[0].generate(1)
@@ -74,22 +75,28 @@ class WalletTest(BitcoinTestFramework):
self.nodes[1].generatetoaddress(101, ADDRESS_WATCHONLY)
self.sync_all()
- assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 50)
- assert_equal(self.nodes[0].getwalletinfo()['balance'], 50)
- assert_equal(self.nodes[1].getbalances()['mine']['trusted'], 50)
+ if not self.options.descriptors:
+ # Tests legacy watchonly behavior which is not present (and does not need to be tested) in descriptor wallets
+ assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 50)
+ assert_equal(self.nodes[0].getwalletinfo()['balance'], 50)
+ assert_equal(self.nodes[1].getbalances()['mine']['trusted'], 50)
- assert_equal(self.nodes[0].getbalances()['watchonly']['immature'], 5000)
- assert 'watchonly' not in self.nodes[1].getbalances()
+ assert_equal(self.nodes[0].getbalances()['watchonly']['immature'], 5000)
+ assert 'watchonly' not in self.nodes[1].getbalances()
- assert_equal(self.nodes[0].getbalance(), 50)
- assert_equal(self.nodes[1].getbalance(), 50)
+ assert_equal(self.nodes[0].getbalance(), 50)
+ assert_equal(self.nodes[1].getbalance(), 50)
self.log.info("Test getbalance with different arguments")
assert_equal(self.nodes[0].getbalance("*"), 50)
assert_equal(self.nodes[0].getbalance("*", 1), 50)
- assert_equal(self.nodes[0].getbalance("*", 1, True), 100)
assert_equal(self.nodes[0].getbalance(minconf=1), 50)
- assert_equal(self.nodes[0].getbalance(minconf=0, include_watchonly=True), 100)
+ if not self.options.descriptors:
+ assert_equal(self.nodes[0].getbalance(minconf=0, include_watchonly=True), 100)
+ assert_equal(self.nodes[0].getbalance("*", 1, True), 100)
+ else:
+ assert_equal(self.nodes[0].getbalance(minconf=0, include_watchonly=True), 50)
+ assert_equal(self.nodes[0].getbalance("*", 1, True), 50)
assert_equal(self.nodes[1].getbalance(minconf=0, include_watchonly=True), 50)
# Send 40 BTC from 0 to 1 and 60 BTC from 1 to 0.
@@ -157,6 +164,8 @@ class WalletTest(BitcoinTestFramework):
expected_balances_1 = {'mine': {'immature': Decimal('0E-8'),
'trusted': Decimal('0E-8'), # node 1's send had an unsafe input
'untrusted_pending': Decimal('30.0') - fee_node_1}} # Doesn't include output of node 0's send since it was spent
+ if self.options.descriptors:
+ del expected_balances_0["watchonly"]
assert_equal(self.nodes[0].getbalances(), expected_balances_0)
assert_equal(self.nodes[1].getbalances(), expected_balances_1)
# getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions
@@ -254,15 +263,13 @@ class WalletTest(BitcoinTestFramework):
self.log.info('Put txs back into mempool of node 1 (not node 0)')
self.nodes[0].invalidateblock(block_reorg)
self.nodes[1].invalidateblock(block_reorg)
- self.sync_blocks()
- self.nodes[0].syncwithvalidationinterfacequeue()
assert_equal(self.nodes[0].getbalance(minconf=0), 0) # wallet txs not in the mempool are untrusted
self.nodes[0].generatetoaddress(1, ADDRESS_WATCHONLY)
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'])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_blocks()
self.nodes[1].sendrawtransaction(tx_orig)
self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY)
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 689a0fa4df..3cbddaf6da 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the wallet."""
from decimal import Decimal
+from itertools import product
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -11,10 +12,11 @@ from test_framework.util import (
assert_equal,
assert_fee_amount,
assert_raises_rpc_error,
- connect_nodes,
)
from test_framework.wallet_util import test_address
+OUT_OF_RANGE = "Amount out of range"
+
class WalletTest(BitcoinTestFramework):
def set_test_params(self):
@@ -32,9 +34,9 @@ class WalletTest(BitcoinTestFramework):
self.setup_nodes()
# Only need nodes 0-2 running at start of test
self.stop_node(3)
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 2)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 2)
+ self.connect_nodes(0, 2)
self.sync_all(self.nodes[0:3])
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
@@ -75,7 +77,7 @@ class WalletTest(BitcoinTestFramework):
assert_equal(len(self.nodes[1].listunspent()), 1)
assert_equal(len(self.nodes[2].listunspent()), 0)
- self.log.info("test gettxout")
+ self.log.info("Test gettxout")
confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"]
# First, outputs that are unspent both in the chain and in the
# mempool should appear with or without include_mempool
@@ -88,7 +90,7 @@ class WalletTest(BitcoinTestFramework):
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
- self.log.info("test gettxout (second part)")
+ self.log.info("Test gettxout (second part)")
# utxo spent in mempool should be visible if you exclude mempool
# but invisible if you include mempool
txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False)
@@ -210,6 +212,8 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), node_2_bal)
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
+ self.log.info("Test sendmany")
+
# Sendmany 10 BTC
txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
self.nodes[2].generate(1)
@@ -226,62 +230,55 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), node_2_bal)
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
- # Sendmany with explicit fee (BTC/kB)
- # Throw if no conf_target provided
- assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
- self.nodes[2].sendmany,
- amounts={ address: 10 },
- estimate_mode='bTc/kB')
- # Throw if negative feerate
- assert_raises_rpc_error(-3, "Amount out of range",
- self.nodes[2].sendmany,
- amounts={ address: 10 },
- conf_target=-1,
- estimate_mode='bTc/kB')
- fee_per_kb = 0.0002500
- explicit_fee_per_byte = Decimal(fee_per_kb) / 1000
- txid = self.nodes[2].sendmany(
- amounts={ address: 10 },
- conf_target=fee_per_kb,
- estimate_mode='bTc/kB',
- )
+ self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)")
+ fee_rate_sat_vb = 2
+ fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
+ explicit_fee_rate_btc_kvb = Decimal(fee_rate_btc_kvb) / 1000
+
+ # Test passing fee_rate as a string
+ txid = self.nodes[2].sendmany(amounts={address: 10}, fee_rate=str(fee_rate_sat_vb))
self.nodes[2].generate(1)
self.sync_all(self.nodes[0:3])
- node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
- assert_equal(self.nodes[2].getbalance(), node_2_bal)
+ balance = self.nodes[2].getbalance()
+ node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_rate_btc_kvb, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
+ assert_equal(balance, node_2_bal)
node_0_bal += Decimal('10')
assert_equal(self.nodes[0].getbalance(), node_0_bal)
- # Sendmany with explicit fee (SAT/B)
- # Throw if no conf_target provided
- assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
- self.nodes[2].sendmany,
- amounts={ address: 10 },
- estimate_mode='sat/b')
- # Throw if negative feerate
- assert_raises_rpc_error(-3, "Amount out of range",
- self.nodes[2].sendmany,
- amounts={ address: 10 },
- conf_target=-1,
- estimate_mode='sat/b')
- fee_sat_per_b = 2
- fee_per_kb = fee_sat_per_b / 100000.0
- explicit_fee_per_byte = Decimal(fee_per_kb) / 1000
- txid = self.nodes[2].sendmany(
- amounts={ address: 10 },
- conf_target=fee_sat_per_b,
- estimate_mode='sAT/b',
- )
+ # Test passing fee_rate as an integer
+ amount = Decimal("0.0001")
+ txid = self.nodes[2].sendmany(amounts={address: amount}, fee_rate=fee_rate_sat_vb)
self.nodes[2].generate(1)
self.sync_all(self.nodes[0:3])
balance = self.nodes[2].getbalance()
- node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
+ node_2_bal = self.check_fee_amount(balance, node_2_bal - amount, explicit_fee_rate_btc_kvb, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
assert_equal(balance, node_2_bal)
- node_0_bal += Decimal('10')
+ node_0_bal += amount
assert_equal(self.nodes[0].getbalance(), node_0_bal)
+ for key in ["totalFee", "feeRate"]:
+ assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)
+
+ # Test setting explicit fee rate just below the minimum.
+ self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
+ assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
+ self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.99999999)
+
+ self.log.info("Test sendmany raises if fee_rate of 0 or -1 is passed")
+ assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
+ self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0)
+ assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1)
+
+ self.log.info("Test sendmany raises if an invalid conf_target or estimate_mode is passed")
+ for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
+ assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h
+ self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)
+ for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
+ assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
+ self.nodes[2].sendmany, amounts={address: 1}, conf_target=target, estimate_mode=mode)
+
self.start_node(3, self.nodes[3].extra_args)
- connect_nodes(self.nodes[0], 3)
+ self.connect_nodes(0, 3)
self.sync_all()
# check if we can list zero value tx as available coins
@@ -311,14 +308,14 @@ class WalletTest(BitcoinTestFramework):
assert_equal(uTx['amount'], Decimal('0'))
assert found
- # do some -walletbroadcast tests
+ self.log.info("Test -walletbroadcast")
self.stop_nodes()
self.start_node(0, ["-walletbroadcast=0"])
self.start_node(1, ["-walletbroadcast=0"])
self.start_node(2, ["-walletbroadcast=0"])
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 2)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 2)
+ self.connect_nodes(0, 2)
self.sync_all(self.nodes[0:3])
txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
@@ -343,9 +340,9 @@ class WalletTest(BitcoinTestFramework):
self.start_node(0)
self.start_node(1)
self.start_node(2)
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[1], 2)
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(1, 2)
+ self.connect_nodes(0, 2)
self.sync_blocks(self.nodes[0:3])
self.nodes[0].generate(1)
@@ -371,7 +368,7 @@ class WalletTest(BitcoinTestFramework):
# General checks for errors from incorrect inputs
# This will raise an exception because the amount is negative
- assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "-1")
+ assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "-1")
# This will raise an exception because the amount type is wrong
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")
@@ -413,73 +410,55 @@ class WalletTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all(self.nodes[0:3])
- # send with explicit btc/kb fee
- self.log.info("test explicit fee (sendtoaddress as btc/kb)")
- self.nodes[0].generate(1)
- self.sync_all(self.nodes[0:3])
+ self.log.info("Test sendtoaddress with fee_rate param (explicit fee rate in sat/vB)")
prebalance = self.nodes[2].getbalance()
assert prebalance > 2
address = self.nodes[1].getnewaddress()
- # Throw if no conf_target provided
- assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
- self.nodes[2].sendtoaddress,
- address=address,
- amount=1.0,
- estimate_mode='BTc/Kb')
- # Throw if negative feerate
- assert_raises_rpc_error(-3, "Amount out of range",
- self.nodes[2].sendtoaddress,
- address=address,
- amount=1.0,
- conf_target=-1,
- estimate_mode='btc/kb')
- txid = self.nodes[2].sendtoaddress(
- address=address,
- amount=1.0,
- conf_target=0.00002500,
- estimate_mode='btc/kb',
- )
+ amount = 3
+ fee_rate_sat_vb = 2
+ fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
+ # Test passing fee_rate as an integer
+ txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=fee_rate_sat_vb)
tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
- self.sync_all(self.nodes[0:3])
self.nodes[0].generate(1)
self.sync_all(self.nodes[0:3])
postbalance = self.nodes[2].getbalance()
- fee = prebalance - postbalance - Decimal('1')
- assert_fee_amount(fee, tx_size, Decimal('0.00002500'))
+ fee = prebalance - postbalance - Decimal(amount)
+ assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))
- # send with explicit sat/b fee
- self.sync_all(self.nodes[0:3])
- self.log.info("test explicit fee (sendtoaddress as sat/b)")
- self.nodes[0].generate(1)
prebalance = self.nodes[2].getbalance()
- assert prebalance > 2
- address = self.nodes[1].getnewaddress()
- # Throw if no conf_target provided
- assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
- self.nodes[2].sendtoaddress,
- address=address,
- amount=1.0,
- estimate_mode='SAT/b')
- # Throw if negative feerate
- assert_raises_rpc_error(-3, "Amount out of range",
- self.nodes[2].sendtoaddress,
- address=address,
- amount=1.0,
- conf_target=-1,
- estimate_mode='SAT/b')
- txid = self.nodes[2].sendtoaddress(
- address=address,
- amount=1.0,
- conf_target=2,
- estimate_mode='SAT/B',
- )
+ amount = Decimal("0.001")
+ fee_rate_sat_vb = 1.23
+ fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
+ # Test passing fee_rate as a string
+ txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=str(fee_rate_sat_vb))
tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
- self.sync_all(self.nodes[0:3])
self.nodes[0].generate(1)
self.sync_all(self.nodes[0:3])
postbalance = self.nodes[2].getbalance()
- fee = prebalance - postbalance - Decimal('1')
- assert_fee_amount(fee, tx_size, Decimal('0.00002000'))
+ fee = prebalance - postbalance - amount
+ assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))
+
+ for key in ["totalFee", "feeRate"]:
+ assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)
+
+ # Test setting explicit fee rate just below the minimum.
+ self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
+ assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
+ self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.99999999)
+
+ self.log.info("Test sendtoaddress raises if fee_rate of 0 or -1 is passed")
+ assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
+ self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=0)
+ assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1)
+
+ self.log.info("Test sendtoaddress raises if an invalid conf_target or estimate_mode is passed")
+ for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
+ assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", # max value of 1008 per src/policy/fees.h
+ self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)
+ for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
+ assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
+ self.nodes[2].sendtoaddress, address=address, amount=1, conf_target=target, estimate_mode=mode)
# 2. Import address from node2 to node1
self.nodes[1].importaddress(address_to_import)
@@ -537,7 +516,7 @@ class WalletTest(BitcoinTestFramework):
]
chainlimit = 6
for m in maintenance:
- self.log.info("check " + m)
+ self.log.info("Test " + m)
self.stop_nodes()
# set lower ancestor limit for later
self.start_node(0, [m, "-limitancestorcount=" + str(chainlimit)])
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index 4b29e65b09..c8c1f2e374 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -29,12 +29,12 @@ from test_framework.util import (
WALLET_PASSPHRASE = "test"
WALLET_PASSPHRASE_TIMEOUT = 3600
-# Fee rates (in BTC per 1000 vbytes)
-INSUFFICIENT = 0.00001000
-ECONOMICAL = 0.00050000
-NORMAL = 0.00100000
-HIGH = 0.00500000
-TOO_HIGH = 1.00000000
+# Fee rates (sat/vB)
+INSUFFICIENT = 1
+ECONOMICAL = 50
+NORMAL = 100
+HIGH = 500
+TOO_HIGH = 100000
class BumpFeeTest(BitcoinTestFramework):
@@ -76,10 +76,9 @@ class BumpFeeTest(BitcoinTestFramework):
self.log.info("Running tests")
dest_address = peer_node.getnewaddress()
- self.test_invalid_parameters(rbf_node, dest_address)
- test_simple_bumpfee_succeeds(self, "default", rbf_node, peer_node, dest_address)
- test_simple_bumpfee_succeeds(self, "fee_rate", rbf_node, peer_node, dest_address)
- test_feerate_args(self, rbf_node, peer_node, dest_address)
+ for mode in ["default", "fee_rate"]:
+ test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address)
+ 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)
@@ -98,28 +97,48 @@ class BumpFeeTest(BitcoinTestFramework):
test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
test_no_more_inputs_fails(self, rbf_node, dest_address)
- def test_invalid_parameters(self, node, dest_address):
- txid = spend_one_input(node, dest_address)
- # invalid estimate mode
- assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
- "estimate_mode": "moo",
- })
- assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
- "estimate_mode": 38,
- })
- assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
- "estimate_mode": {
- "foo": "bar",
- },
- })
- assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
- "estimate_mode": Decimal("3.141592"),
- })
- # confTarget and conf_target
- assert_raises_rpc_error(-8, "confTarget and conf_target options should not both be set", node.bumpfee, txid, {
- "confTarget": 123,
- "conf_target": 456,
- })
+ def test_invalid_parameters(self, rbf_node, peer_node, dest_address):
+ self.log.info('Test invalid parameters')
+ rbfid = spend_one_input(rbf_node, dest_address)
+ self.sync_mempools((rbf_node, peer_node))
+ assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
+
+ for key in ["totalFee", "feeRate"]:
+ assert_raises_rpc_error(-3, "Unexpected key {}".format(key), rbf_node.bumpfee, rbfid, {key: NORMAL})
+
+ # Bumping to just above minrelay should fail to increase the total fee enough.
+ assert_raises_rpc_error(-8, "Insufficient total fee 0.00000141", rbf_node.bumpfee, rbfid, {"fee_rate": INSUFFICIENT})
+
+ self.log.info("Test invalid fee rate settings")
+ assert_raises_rpc_error(-8, "Insufficient total fee 0.00", rbf_node.bumpfee, rbfid, {"fee_rate": 0})
+ assert_raises_rpc_error(-4, "Specified or calculated fee 0.141 is too high (cannot be higher than -maxtxfee 0.10",
+ rbf_node.bumpfee, rbfid, {"fee_rate": TOO_HIGH})
+ assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, {"fee_rate": -1})
+ for value in [{"foo": "bar"}, True]:
+ assert_raises_rpc_error(-3, "Amount is not a number or string", rbf_node.bumpfee, rbfid, {"fee_rate": value})
+ assert_raises_rpc_error(-3, "Invalid amount", rbf_node.bumpfee, rbfid, {"fee_rate": ""})
+
+ self.log.info("Test explicit fee rate raises RPC error if both fee_rate and conf_target are passed")
+ assert_raises_rpc_error(-8, "Cannot specify both conf_target and fee_rate. Please provide either a confirmation "
+ "target in blocks for automatic fee estimation, or an explicit fee rate.",
+ rbf_node.bumpfee, rbfid, {"conf_target": NORMAL, "fee_rate": NORMAL})
+
+ self.log.info("Test explicit fee rate raises RPC error if both fee_rate and estimate_mode are passed")
+ assert_raises_rpc_error(-8, "Cannot specify both estimate_mode and fee_rate",
+ rbf_node.bumpfee, rbfid, {"estimate_mode": "economical", "fee_rate": NORMAL})
+
+ self.log.info("Test invalid conf_target settings")
+ assert_raises_rpc_error(-8, "confTarget and conf_target options should not both be set",
+ rbf_node.bumpfee, rbfid, {"confTarget": 123, "conf_target": 456})
+
+ self.log.info("Test invalid estimate_mode settings")
+ for k, v in {"number": 42, "object": {"foo": "bar"}}.items():
+ assert_raises_rpc_error(-3, "Expected type string for estimate_mode, got {}".format(k),
+ rbf_node.bumpfee, rbfid, {"estimate_mode": v})
+ for mode in ["foo", Decimal("3.1415"), "sat/B", "BTC/kB"]:
+ assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"',
+ rbf_node.bumpfee, rbfid, {"estimate_mode": mode})
+
self.clear_mempool()
@@ -130,7 +149,7 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
self.sync_mempools((rbf_node, peer_node))
assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
if mode == "fee_rate":
- bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"fee_rate": NORMAL})
+ bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"fee_rate": str(NORMAL)})
bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": NORMAL})
else:
bumped_psbt = rbf_node.psbtbumpfee(rbfid)
@@ -158,33 +177,13 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
self.clear_mempool()
-def test_feerate_args(self, rbf_node, peer_node, dest_address):
- self.log.info('Test fee_rate args')
- rbfid = spend_one_input(rbf_node, dest_address)
- self.sync_mempools((rbf_node, peer_node))
- assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
-
- assert_raises_rpc_error(-8, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL, "confTarget": 1})
-
- assert_raises_rpc_error(-3, "Unexpected key totalFee", rbf_node.bumpfee, rbfid, {"totalFee": NORMAL})
- assert_raises_rpc_error(-8, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate":0.00001, "confTarget": 1})
-
- # Bumping to just above minrelay should fail to increase total fee enough, at least
- assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, rbfid, {"fee_rate": INSUFFICIENT})
-
- assert_raises_rpc_error(-3, "Amount out of range", rbf_node.bumpfee, rbfid, {"fee_rate": -1})
-
- assert_raises_rpc_error(-4, "is too high (cannot be higher than", rbf_node.bumpfee, rbfid, {"fee_rate": TOO_HIGH})
- self.clear_mempool()
-
-
def test_segwit_bumpfee_succeeds(self, rbf_node, dest_address):
self.log.info('Test that segwit-sourcing bumpfee works')
# Create a transaction with segwit output, then create an RBF transaction
# which spends it, and make sure bumpfee can be called on it.
segwit_in = next(u for u in rbf_node.listunspent() if u["amount"] == Decimal("0.001"))
- segwit_out = rbf_node.getaddressinfo(rbf_node.getnewaddress(address_type='p2sh-segwit'))
+ segwit_out = rbf_node.getaddressinfo(rbf_node.getnewaddress(address_type='bech32'))
segwitid = send_to_witness(
use_p2wsh=False,
node=rbf_node,
@@ -303,11 +302,11 @@ def test_dust_to_fee(self, rbf_node, dest_address):
# boundary. Thus expected transaction size (p2wpkh, 1 input, 2 outputs) is 140-141 vbytes, usually 141.
if not 140 <= fulltx["vsize"] <= 141:
raise AssertionError("Invalid tx vsize of {} (140-141 expected), full tx: {}".format(fulltx["vsize"], fulltx))
- # Bump with fee_rate of 0.00350250 BTC per 1000 vbytes to create dust.
+ # Bump with fee_rate of 350.25 sat/vB vbytes to create dust.
# Expected fee is 141 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049385 BTC.
# or occasionally 140 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049035 BTC.
# Dust should be dropped to the fee, so actual bump fee is 0.00050000 BTC.
- bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 0.00350250})
+ bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": 350.25})
full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
assert_equal(bumped_tx["fee"], Decimal("0.00050000"))
assert_equal(len(fulltx["vout"]), 2)
@@ -365,7 +364,7 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
rbf_node.createwallet(wallet_name="signer", disable_private_keys=False, blank=True)
signer = rbf_node.get_wallet_rpc("signer")
assert signer.getwalletinfo()['private_keys_enabled']
- result = signer.importmulti([{
+ reqs = [{
"desc": priv_rec_desc,
"timestamp": 0,
"range": [0,1],
@@ -378,7 +377,11 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
"range": [0, 0],
"internal": True,
"keypool": False
- }])
+ }]
+ if self.options.descriptors:
+ result = signer.importdescriptors(reqs)
+ else:
+ result = signer.importmulti(reqs)
assert_equal(result, [{'success': True}, {'success': True}])
# Create another wallet with just the public keys, which creates PSBTs
@@ -386,21 +389,27 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
watcher = rbf_node.get_wallet_rpc("watcher")
assert not watcher.getwalletinfo()['private_keys_enabled']
- result = watcher.importmulti([{
+ reqs = [{
"desc": pub_rec_desc,
"timestamp": 0,
"range": [0, 10],
"internal": False,
"keypool": True,
- "watchonly": True
+ "watchonly": True,
+ "active": True,
}, {
"desc": pub_change_desc,
"timestamp": 0,
"range": [0, 10],
"internal": True,
"keypool": True,
- "watchonly": True
- }])
+ "watchonly": True,
+ "active": True,
+ }]
+ if self.options.descriptors:
+ result = watcher.importdescriptors(reqs)
+ else:
+ result = watcher.importmulti(reqs)
assert_equal(result, [{'success': True}, {'success': True}])
funding_address1 = watcher.getnewaddress(address_type='bech32')
@@ -410,7 +419,7 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address):
self.sync_all()
# Create single-input PSBT for transaction to be bumped
- psbt = watcher.walletcreatefundedpsbt([], {dest_address: 0.0005}, 0, {"feeRate": 0.00001}, True)['psbt']
+ psbt = watcher.walletcreatefundedpsbt([], {dest_address: 0.0005}, 0, {"fee_rate": 1}, True)['psbt']
psbt_signed = signer.walletprocesspsbt(psbt=psbt, sign=True, sighashtype="ALL", bip32derivs=True)
psbt_final = watcher.finalizepsbt(psbt_signed["psbt"])
original_txid = watcher.sendrawtransaction(psbt_final["hex"])
diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py
index 48c0fcb731..cf3317121f 100755
--- a/test/functional/wallet_createwallet.py
+++ b/test/functional/wallet_createwallet.py
@@ -5,11 +5,15 @@
"""Test createwallet arguments.
"""
+from test_framework.address import key_to_p2wpkh
+from test_framework.descriptors import descsum_create
+from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
)
+from test_framework.wallet_util import bytes_to_wif, generate_wif_key
class CreateWalletTest(BitcoinTestFramework):
def set_test_params(self):
@@ -35,10 +39,14 @@ class CreateWalletTest(BitcoinTestFramework):
w1.importpubkey(w0.getaddressinfo(address1)['pubkey'])
self.log.info('Test that private keys cannot be imported')
- addr = w0.getnewaddress('', 'legacy')
- privkey = w0.dumpprivkey(addr)
+ eckey = ECKey()
+ eckey.generate()
+ privkey = bytes_to_wif(eckey.get_bytes())
assert_raises_rpc_error(-4, 'Cannot import private keys to a wallet with private keys disabled', w1.importprivkey, privkey)
- result = w1.importmulti([{'scriptPubKey': {'address': addr}, 'timestamp': 'now', 'keys': [privkey]}])
+ if self.options.descriptors:
+ result = w1.importdescriptors([{'desc': descsum_create('wpkh(' + privkey + ')'), 'timestamp': 'now'}])
+ else:
+ result = w1.importmulti([{'scriptPubKey': {'address': key_to_p2wpkh(eckey.get_pubkey().get_bytes())}, 'timestamp': 'now', 'keys': [privkey]}])
assert not result[0]['success']
assert 'warning' not in result[0]
assert_equal(result[0]['error']['code'], -4)
@@ -58,12 +66,25 @@ class CreateWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getrawchangeaddress)
# Import private key
- w3.importprivkey(w0.dumpprivkey(address1))
+ w3.importprivkey(generate_wif_key())
# Imported private keys are currently ignored by the keypool
assert_equal(w3.getwalletinfo()['keypoolsize'], 0)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w3.getnewaddress)
# Set the seed
- w3.sethdseed()
+ if self.options.descriptors:
+ w3.importdescriptors([{
+ 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/0h/*)'),
+ 'timestamp': 'now',
+ 'active': True
+ },
+ {
+ 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/1h/*)'),
+ 'timestamp': 'now',
+ 'active': True,
+ 'internal': True
+ }])
+ else:
+ w3.sethdseed()
assert_equal(w3.getwalletinfo()['keypoolsize'], 1)
w3.getnewaddress()
w3.getrawchangeaddress()
@@ -80,7 +101,20 @@ class CreateWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w4.getrawchangeaddress)
# Now set a seed and it should work. Wallet should also be encrypted
w4.walletpassphrase('pass', 60)
- w4.sethdseed()
+ if self.options.descriptors:
+ w4.importdescriptors([{
+ 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/0h/*)'),
+ 'timestamp': 'now',
+ 'active': True
+ },
+ {
+ 'desc': descsum_create('wpkh(tprv8ZgxMBicQKsPcwuZGKp8TeWppSuLMiLe2d9PupB14QpPeQsqoj3LneJLhGHH13xESfvASyd4EFLJvLrG8b7DrLxEuV7hpF9uUc6XruKA1Wq/1h/*)'),
+ 'timestamp': 'now',
+ 'active': True,
+ 'internal': True
+ }])
+ else:
+ w4.sethdseed()
w4.getnewaddress()
w4.getrawchangeaddress()
@@ -111,13 +145,14 @@ class CreateWalletTest(BitcoinTestFramework):
w6.walletpassphrase('thisisapassphrase', 60)
w6.signmessage(w6.getnewaddress('', 'legacy'), "test")
w6.keypoolrefill(1)
- # There should only be 1 key
+ # There should only be 1 key for legacy, 3 for descriptors
walletinfo = w6.getwalletinfo()
- assert_equal(walletinfo['keypoolsize'], 1)
- assert_equal(walletinfo['keypoolsize_hd_internal'], 1)
+ keys = 3 if self.options.descriptors else 1
+ assert_equal(walletinfo['keypoolsize'], keys)
+ assert_equal(walletinfo['keypoolsize_hd_internal'], keys)
# Allow empty passphrase, but there should be a warning
resp = self.nodes[0].createwallet(wallet_name='w7', disable_private_keys=False, blank=False, passphrase='')
- assert_equal(resp['warning'], 'Empty string given as passphrase, wallet will not be encrypted.')
+ assert 'Empty string given as passphrase, wallet will not be encrypted.' in resp['warning']
w7 = node.get_wallet_rpc('w7')
assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 60)
diff --git a/test/functional/wallet_descriptor.py b/test/functional/wallet_descriptor.py
index 62eb15f87a..0fec8ea4a4 100755
--- a/test/functional/wallet_descriptor.py
+++ b/test/functional/wallet_descriptor.py
@@ -16,19 +16,27 @@ class WalletDescriptorTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [['-keypool=100']]
+ self.wallet_names = []
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
+ self.skip_if_no_sqlite()
def run_test(self):
+ # Make a legacy wallet and check it is BDB
+ self.nodes[0].createwallet(wallet_name="legacy1", descriptors=False)
+ wallet_info = self.nodes[0].getwalletinfo()
+ assert_equal(wallet_info['format'], 'bdb')
+ self.nodes[0].unloadwallet("legacy1")
+
# Make a descriptor wallet
self.log.info("Making a descriptor wallet")
self.nodes[0].createwallet(wallet_name="desc1", descriptors=True)
- self.nodes[0].unloadwallet(self.default_wallet_name)
# A descriptor wallet should have 100 addresses * 3 types = 300 keys
self.log.info("Checking wallet info")
wallet_info = self.nodes[0].getwalletinfo()
+ assert_equal(wallet_info['format'], 'sqlite')
assert_equal(wallet_info['keypoolsize'], 300)
assert_equal(wallet_info['keypoolsize_hd_internal'], 300)
assert 'keypoololdest' not in wallet_info
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index 09581d864b..eb54da99f5 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -95,7 +95,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
class WalletDumpTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
- self.extra_args = [["-keypool=90", "-addresstype=legacy", "-wallet=dump"]]
+ self.extra_args = [["-keypool=90", "-addresstype=legacy"]]
self.rpc_timeout = 120
def skip_test_if_missing_module(self):
@@ -106,6 +106,8 @@ class WalletDumpTest(BitcoinTestFramework):
self.start_nodes()
def run_test(self):
+ self.nodes[0].createwallet("dump")
+
wallet_unenc_dump = os.path.join(self.nodes[0].datadir, "wallet.unencrypted.dump")
wallet_enc_dump = os.path.join(self.nodes[0].datadir, "wallet.encrypted.dump")
@@ -190,7 +192,8 @@ class WalletDumpTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "already exists", lambda: self.nodes[0].dumpwallet(wallet_enc_dump))
# Restart node with new wallet, and test importwallet
- self.restart_node(0, ['-wallet=w2'])
+ self.restart_node(0)
+ self.nodes[0].createwallet("w2")
# Make sure the address is not IsMine before import
result = self.nodes[0].getaddressinfo(multisig_addr)
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index 5af14ecb8f..d45cf05689 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -10,7 +10,6 @@ import shutil
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
assert_raises_rpc_error,
)
@@ -99,7 +98,7 @@ class WalletHDTest(BitcoinTestFramework):
assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/" + str(i) + "'")
assert_equal(hd_info_2["hdmasterfingerprint"], hd_fingerprint)
assert_equal(hd_add, hd_add_2)
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_all()
# Needs rescan
@@ -115,7 +114,7 @@ class WalletHDTest(BitcoinTestFramework):
os.path.join(self.nodes[1].datadir, self.chain, "wallets", self.default_wallet_name, self.wallet_data_filename),
)
self.start_node(1, extra_args=self.extra_args[1])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
self.sync_all()
# Wallet automatically scans blocks older than key on startup
assert_equal(self.nodes[1].getbalance(), NUM_HD_ADDS + 1)
@@ -183,7 +182,7 @@ class WalletHDTest(BitcoinTestFramework):
# Restart node 1 with keypool of 3 and a different wallet
self.nodes[1].createwallet(wallet_name='origin', blank=True)
self.restart_node(1, extra_args=['-keypool=3', '-wallet=origin'])
- connect_nodes(self.nodes[0], 1)
+ self.connect_nodes(0, 1)
# sethdseed restoring and seeing txs to addresses out of the keypool
origin_rpc = self.nodes[1].get_wallet_rpc('origin')
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index 9d532742ee..aad112b499 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -22,7 +22,6 @@ happened previously.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.address import AddressType
from test_framework.util import (
- connect_nodes,
assert_equal,
set_node_times,
)
@@ -165,7 +164,7 @@ class ImportRescanTest(BitcoinTestFramework):
self.start_nodes()
for i in range(1, self.num_nodes):
- connect_nodes(self.nodes[i], 0)
+ self.connect_nodes(i, 0)
def run_test(self):
# Create one transaction on node 0 with a unique amount for
@@ -182,6 +181,7 @@ class ImportRescanTest(BitcoinTestFramework):
self.nodes[0].generate(1) # Generate one block for each send
variant.confirmation_height = self.nodes[0].getblockcount()
variant.timestamp = self.nodes[0].getblockheader(self.nodes[0].getbestblockhash())["time"]
+ self.sync_all() # Conclude sync before calling setmocktime to avoid timeouts
# Generate a block further in the future (past the rescan window).
assert_equal(self.nodes[0].getrawmempool(), [])
diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py
index 2d982edef8..2903a84998 100755
--- a/test/functional/wallet_importdescriptors.py
+++ b/test/functional/wallet_importdescriptors.py
@@ -15,6 +15,7 @@ variants.
- `test_address()` is called to call getaddressinfo for an address on node1
and test the values returned."""
+from test_framework.address import key_to_p2pkh
from test_framework.test_framework import BitcoinTestFramework
from test_framework.descriptors import descsum_create
from test_framework.util import (
@@ -34,9 +35,11 @@ class ImportDescriptorsTest(BitcoinTestFramework):
["-addresstype=bech32", "-keypool=5"]
]
self.setup_clean_chain = True
+ self.wallet_names = []
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
+ self.skip_if_no_sqlite()
def test_importdesc(self, req, success, error_code=None, error_message=None, warnings=None, wallet=None):
"""Run importdescriptors and assert success"""
@@ -58,7 +61,7 @@ class ImportDescriptorsTest(BitcoinTestFramework):
def run_test(self):
self.log.info('Setting up wallets')
- self.nodes[0].createwallet(wallet_name='w0', disable_private_keys=False)
+ self.nodes[0].createwallet(wallet_name='w0', disable_private_keys=False, descriptors=True)
w0 = self.nodes[0].get_wallet_rpc('w0')
self.nodes[1].createwallet(wallet_name='w1', disable_private_keys=True, blank=True, descriptors=True)
@@ -105,6 +108,17 @@ class ImportDescriptorsTest(BitcoinTestFramework):
error_code=-8,
error_message="Internal addresses should not have a label")
+ self.log.info("Internal addresses should be detected as such")
+ key = get_generate_key()
+ addr = key_to_p2pkh(key.pubkey)
+ self.test_importdesc({"desc": descsum_create("pkh(" + key.pubkey + ")"),
+ "timestamp": "now",
+ "internal": True},
+ success=True)
+ info = w1.getaddressinfo(addr)
+ assert_equal(info["ismine"], True)
+ assert_equal(info["ischange"], True)
+
# # Test importing of a P2SH-P2WPKH descriptor
key = get_generate_key()
self.log.info("Should not import a p2sh-p2wpkh descriptor without checksum")
@@ -207,6 +221,15 @@ class ImportDescriptorsTest(BitcoinTestFramework):
success=False,
error_code=-4,
error_message='Cannot import private keys to a wallet with private keys disabled')
+
+ self.log.info("Should not import a descriptor with hardened derivations when private keys are disabled")
+ self.test_importdesc({"desc": descsum_create("wpkh(" + xpub + "/1h/*)"),
+ "timestamp": "now",
+ "range": 1},
+ success=False,
+ error_code=-4,
+ error_message='Cannot expand descriptor. Probably because of hardened derivations without private keys provided')
+
for address in addresses:
test_address(w1,
address,
diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py
index f7fdd6e908..30206349ae 100755
--- a/test/functional/wallet_importmulti.py
+++ b/test/functional/wallet_importmulti.py
@@ -64,7 +64,7 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
- self.nodes[1].syncwithvalidationinterfacequeue()
+ self.nodes[1].syncwithvalidationinterfacequeue() # Sync the timestamp to the wallet, so that importmulti works
node0_address1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py
index 78426018ef..d10d8ae1c8 100755
--- a/test/functional/wallet_importprunedfunds.py
+++ b/test/functional/wallet_importprunedfunds.py
@@ -5,11 +5,14 @@
"""Test the importprunedfunds and removeprunedfunds RPCs."""
from decimal import Decimal
+from test_framework.address import key_to_p2wpkh
+from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
)
+from test_framework.wallet_util import bytes_to_wif
class ImportPrunedFundsTest(BitcoinTestFramework):
def set_test_params(self):
@@ -30,8 +33,11 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
# pubkey
address2 = self.nodes[0].getnewaddress()
# privkey
- address3 = self.nodes[0].getnewaddress()
- address3_privkey = self.nodes[0].dumpprivkey(address3) # Using privkey
+ eckey = ECKey()
+ eckey.generate()
+ address3_privkey = bytes_to_wif(eckey.get_bytes())
+ address3 = key_to_p2wpkh(eckey.get_pubkey().get_bytes())
+ self.nodes[0].importprivkey(address3_privkey)
# Check only one address
address_info = self.nodes[0].getaddressinfo(address1)
@@ -80,37 +86,44 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
assert_equal(balance1, Decimal(0))
# Import with affiliated address with no rescan
- self.nodes[1].importaddress(address=address2, rescan=False)
- self.nodes[1].importprunedfunds(rawtransaction=rawtxn2, txoutproof=proof2)
- assert [tx for tx in self.nodes[1].listtransactions(include_watchonly=True) if tx['txid'] == txnid2]
+ self.nodes[1].createwallet('wwatch', disable_private_keys=True)
+ wwatch = self.nodes[1].get_wallet_rpc('wwatch')
+ wwatch.importaddress(address=address2, rescan=False)
+ wwatch.importprunedfunds(rawtransaction=rawtxn2, txoutproof=proof2)
+ assert [tx for tx in wwatch.listtransactions(include_watchonly=True) if tx['txid'] == txnid2]
# Import with private key with no rescan
- self.nodes[1].importprivkey(privkey=address3_privkey, rescan=False)
- self.nodes[1].importprunedfunds(rawtxn3, proof3)
- assert [tx for tx in self.nodes[1].listtransactions() if tx['txid'] == txnid3]
- balance3 = self.nodes[1].getbalance()
+ w1 = self.nodes[1].get_wallet_rpc(self.default_wallet_name)
+ w1.importprivkey(privkey=address3_privkey, rescan=False)
+ w1.importprunedfunds(rawtxn3, proof3)
+ assert [tx for tx in w1.listtransactions() if tx['txid'] == txnid3]
+ balance3 = w1.getbalance()
assert_equal(balance3, Decimal('0.025'))
# Addresses Test - after import
- address_info = self.nodes[1].getaddressinfo(address1)
+ address_info = w1.getaddressinfo(address1)
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], False)
- address_info = self.nodes[1].getaddressinfo(address2)
- assert_equal(address_info['iswatchonly'], True)
- assert_equal(address_info['ismine'], False)
- address_info = self.nodes[1].getaddressinfo(address3)
+ address_info = wwatch.getaddressinfo(address2)
+ if self.options.descriptors:
+ assert_equal(address_info['iswatchonly'], False)
+ assert_equal(address_info['ismine'], True)
+ else:
+ assert_equal(address_info['iswatchonly'], True)
+ assert_equal(address_info['ismine'], False)
+ address_info = w1.getaddressinfo(address3)
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], True)
# Remove transactions
- assert_raises_rpc_error(-8, "Transaction does not exist in wallet.", self.nodes[1].removeprunedfunds, txnid1)
- assert not [tx for tx in self.nodes[1].listtransactions(include_watchonly=True) if tx['txid'] == txnid1]
+ assert_raises_rpc_error(-8, "Transaction does not exist in wallet.", w1.removeprunedfunds, txnid1)
+ assert not [tx for tx in w1.listtransactions(include_watchonly=True) if tx['txid'] == txnid1]
- self.nodes[1].removeprunedfunds(txnid2)
- assert not [tx for tx in self.nodes[1].listtransactions(include_watchonly=True) if tx['txid'] == txnid2]
+ wwatch.removeprunedfunds(txnid2)
+ assert not [tx for tx in wwatch.listtransactions(include_watchonly=True) if tx['txid'] == txnid2]
- self.nodes[1].removeprunedfunds(txnid3)
- assert not [tx for tx in self.nodes[1].listtransactions(include_watchonly=True) if tx['txid'] == txnid3]
+ w1.removeprunedfunds(txnid3)
+ assert not [tx for tx in w1.listtransactions(include_watchonly=True) if tx['txid'] == txnid3]
if __name__ == '__main__':
ImportPrunedFundsTest().main()
diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py
index 3f865b330c..78e06c5916 100755
--- a/test/functional/wallet_keypool_topup.py
+++ b/test/functional/wallet_keypool_topup.py
@@ -16,7 +16,6 @@ import shutil
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
)
@@ -38,9 +37,9 @@ class KeypoolRestoreTest(BitcoinTestFramework):
self.stop_node(1)
shutil.copyfile(wallet_path, wallet_backup_path)
self.start_node(1, self.extra_args[1])
- connect_nodes(self.nodes[0], 1)
- connect_nodes(self.nodes[0], 2)
- connect_nodes(self.nodes[0], 3)
+ self.connect_nodes(0, 1)
+ self.connect_nodes(0, 2)
+ self.connect_nodes(0, 3)
for i, output_type in enumerate(["legacy", "p2sh-segwit", "bech32"]):
@@ -72,7 +71,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
self.stop_node(idx)
shutil.copyfile(wallet_backup_path, wallet_path)
self.start_node(idx, self.extra_args[idx])
- connect_nodes(self.nodes[0], idx)
+ self.connect_nodes(0, idx)
self.sync_all()
self.log.info("Verify keypool is restored and balance is correct")
diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py
index cff59bd1c1..883b97561e 100755
--- a/test/functional/wallet_labels.py
+++ b/test/functional/wallet_labels.py
@@ -135,7 +135,7 @@ class WalletLabelsTest(BitcoinTestFramework):
change_label(node, labels[2].addresses[0], labels[2], labels[2])
self.log.info('Check watchonly labels')
- node.createwallet(wallet_name='watch_only', disable_private_keys=True, descriptors=False)
+ node.createwallet(wallet_name='watch_only', disable_private_keys=True)
wallet_watch_only = node.get_wallet_rpc('watch_only')
BECH32_VALID = {
'✔️_VER15_PROG40': 'bcrt10qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqn2cjv3',
@@ -156,7 +156,7 @@ class WalletLabelsTest(BitcoinTestFramework):
ad = BECH32_INVALID[l]
assert_raises_rpc_error(
-5,
- "Invalid Bitcoin address or script",
+ "Address is not valid" if self.options.descriptors else "Invalid Bitcoin address or script",
lambda: wallet_watch_only.importaddress(label=l, rescan=False, address=ad),
)
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index d4131deabf..6a1b9097c5 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -4,14 +4,16 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the listsinceblock RPC."""
+from test_framework.address import key_to_p2wpkh
+from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.messages import BIP125_SEQUENCE_NUMBER
from test_framework.util import (
assert_array_result,
assert_equal,
assert_raises_rpc_error,
- connect_nodes,
)
+from test_framework.wallet_util import bytes_to_wif
from decimal import Decimal
@@ -26,7 +28,7 @@ class ListSinceBlockTest(BitcoinTestFramework):
def run_test(self):
# All nodes are in IBD from genesis, so they'll need the miner (node2) to be an outbound connection, or have
# only one connection. (See fPreferredDownload in net_processing)
- connect_nodes(self.nodes[1], 2)
+ self.connect_nodes(1, 2)
self.nodes[2].generate(101)
self.sync_all()
@@ -182,15 +184,22 @@ class ListSinceBlockTest(BitcoinTestFramework):
self.sync_all()
- # Split network into two
- self.split_network()
-
# share utxo between nodes[1] and nodes[2]
+ eckey = ECKey()
+ eckey.generate()
+ privkey = bytes_to_wif(eckey.get_bytes())
+ address = key_to_p2wpkh(eckey.get_pubkey().get_bytes())
+ self.nodes[2].sendtoaddress(address, 10)
+ self.nodes[2].generate(6)
+ self.sync_all()
+ self.nodes[2].importprivkey(privkey)
utxos = self.nodes[2].listunspent()
- utxo = utxos[0]
- privkey = self.nodes[2].dumpprivkey(utxo['address'])
+ utxo = [u for u in utxos if u["address"] == address][0]
self.nodes[1].importprivkey(privkey)
+ # Split network into two
+ self.split_network()
+
# send from nodes[1] using utxo to nodes[0]
change = '%.8f' % (float(utxo['amount']) - 1.0003)
recipient_dict = {
diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py
index 8ff663ccd2..3e98208431 100755
--- a/test/functional/wallet_listtransactions.py
+++ b/test/functional/wallet_listtransactions.py
@@ -91,18 +91,20 @@ class ListTransactionsTest(BitcoinTestFramework):
{"category": "receive", "amount": Decimal("0.44")},
{"txid": txid})
- pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
- multisig = self.nodes[1].createmultisig(1, [pubkey])
- self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
- txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
- self.nodes[1].generate(1)
- self.sync_all()
- assert_equal(len(self.nodes[0].listtransactions(label="watchonly", include_watchonly=True)), 1)
- assert_equal(len(self.nodes[0].listtransactions(dummy="watchonly", include_watchonly=True)), 1)
- assert len(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=False)) == 0
- assert_array_result(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=True),
- {"category": "receive", "amount": Decimal("0.1")},
- {"txid": txid, "label": "watchonly"})
+ if not self.options.descriptors:
+ # include_watchonly is a legacy wallet feature, so don't test it for descriptor wallets
+ pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
+ multisig = self.nodes[1].createmultisig(1, [pubkey])
+ self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
+ txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
+ self.nodes[1].generate(1)
+ self.sync_all()
+ assert_equal(len(self.nodes[0].listtransactions(label="watchonly", include_watchonly=True)), 1)
+ assert_equal(len(self.nodes[0].listtransactions(dummy="watchonly", include_watchonly=True)), 1)
+ assert len(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=False)) == 0
+ assert_array_result(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=True),
+ {"category": "receive", "amount": Decimal("0.1")},
+ {"txid": txid, "label": "watchonly"})
self.run_rbf_opt_in_test()
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 61791a756c..bb89e76a9a 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -10,6 +10,7 @@ from decimal import Decimal
from threading import Thread
import os
import shutil
+import stat
import time
from test_framework.authproxy import JSONRPCException
@@ -22,9 +23,11 @@ from test_framework.util import (
)
got_loading_error = False
+
+
def test_load_unload(node, name):
global got_loading_error
- for _ in range(10):
+ while True:
if got_loading_error:
return
try:
@@ -41,6 +44,7 @@ class MultiWalletTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
self.rpc_timeout = 120
+ self.extra_args = [["-nowallet"], []]
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -66,7 +70,7 @@ class MultiWalletTest(BitcoinTestFramework):
return wallet_dir(name, "wallet.dat")
return wallet_dir(name)
- assert_equal(self.nodes[0].listwalletdir(), { 'wallets': [{ 'name': self.default_wallet_name }] })
+ assert_equal(self.nodes[0].listwalletdir(), {'wallets': [{'name': self.default_wallet_name}]})
# check wallet.dat is created
self.stop_nodes()
@@ -77,10 +81,17 @@ class MultiWalletTest(BitcoinTestFramework):
os.mkdir(wallet_dir('w7'))
os.symlink('w7', wallet_dir('w7_symlink'))
+ os.symlink('..', wallet_dir('recursive_dir_symlink'))
+
+ os.mkdir(wallet_dir('self_walletdat_symlink'))
+ os.symlink('wallet.dat', wallet_dir('self_walletdat_symlink/wallet.dat'))
+
# rename wallet.dat to make sure plain wallet file paths (as opposed to
# directory paths) can be loaded
# create another dummy wallet for use in testing backups later
- self.start_node(0, ["-nowallet", "-wallet=empty", "-wallet=plain"])
+ self.start_node(0)
+ node.createwallet("empty")
+ node.createwallet("plain")
node.createwallet("created")
self.stop_nodes()
empty_wallet = os.path.join(self.options.tmpdir, 'empty.dat')
@@ -98,35 +109,58 @@ class MultiWalletTest(BitcoinTestFramework):
# sub/w5 - to verify relative wallet path is created correctly
# extern/w6 - to verify absolute wallet path is created correctly
# w7_symlink - to verify symlinked wallet path is initialized correctly
- # w8 - to verify existing wallet file is loaded correctly
+ # w8 - to verify existing wallet file is loaded correctly. Not tested for SQLite wallets as this is a deprecated BDB behavior.
# '' - to verify default wallet file is created correctly
- wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', 'w8', self.default_wallet_name]
- extra_args = ['-nowallet'] + ['-wallet={}'.format(n) for n in wallet_names]
- self.start_node(0, extra_args)
- assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), [self.default_wallet_name, os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8'])
+ to_create = ['w1', 'w2', 'w3', 'w', 'sub/w5', 'w7_symlink']
+ in_wallet_dir = [w.replace('/', os.path.sep) for w in to_create] # Wallets in the wallet dir
+ in_wallet_dir.append('w7') # w7 is not loaded or created, but will be listed by listwalletdir because w7_symlink
+ to_create.append(os.path.join(self.options.tmpdir, 'extern/w6')) # External, not in the wallet dir, so we need to avoid adding it to in_wallet_dir
+ to_load = [self.default_wallet_name]
+ if not self.options.descriptors:
+ to_load.append('w8')
+ wallet_names = to_create + to_load # Wallet names loaded in the wallet
+ in_wallet_dir += to_load # The loaded wallets are also in the wallet dir
+ self.start_node(0)
+ for wallet_name in to_create:
+ self.nodes[0].createwallet(wallet_name)
+ for wallet_name in to_load:
+ self.nodes[0].loadwallet(wallet_name)
+
+ os.mkdir(wallet_dir('no_access'))
+ os.chmod(wallet_dir('no_access'), 0)
+ try:
+ with self.nodes[0].assert_debug_log(expected_msgs=['Error scanning']):
+ walletlist = self.nodes[0].listwalletdir()['wallets']
+ finally:
+ # Need to ensure access is restored for cleanup
+ os.chmod(wallet_dir('no_access'), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
+ assert_equal(sorted(map(lambda w: w['name'], walletlist)), sorted(in_wallet_dir))
assert_equal(set(node.listwallets()), set(wallet_names))
+ # should raise rpc error if wallet path can't be created
+ err_code = -4 if self.options.descriptors else -1
+ assert_raises_rpc_error(err_code, "boost::filesystem::create_directory:", self.nodes[0].createwallet, "w8/bad")
+
# check that all requested wallets were created
self.stop_node(0)
for wallet_name in wallet_names:
assert_equal(os.path.isfile(wallet_file(wallet_name)), True)
- # should not initialize if wallet path can't be created
- exp_stderr = "boost::filesystem::create_directory:"
- self.nodes[0].assert_start_raises_init_error(['-wallet=w8/bad'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
-
self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist')
self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" is a relative path', cwd=data_dir())
self.nodes[0].assert_start_raises_init_error(['-walletdir=debug.log'], 'Error: Specified -walletdir "debug.log" is not a directory', cwd=data_dir())
- # should not initialize if there are duplicate wallets
- self.nodes[0].assert_start_raises_init_error(['-wallet=w1', '-wallet=w1'], 'Error: Error loading wallet w1. Duplicate -wallet filename specified.')
+ self.start_node(0, ['-wallet=w1', '-wallet=w1'])
+ self.stop_node(0, 'Warning: Ignoring duplicate -wallet w1.')
- # should not initialize if one wallet is a copy of another
- shutil.copyfile(wallet_dir('w8'), wallet_dir('w8_copy'))
- exp_stderr = r"BerkeleyDatabase: Can't open database w8_copy \(duplicates fileid \w+ from w8\)"
- self.nodes[0].assert_start_raises_init_error(['-wallet=w8', '-wallet=w8_copy'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
+ if not self.options.descriptors:
+ # Only BDB doesn't open duplicate wallet files. SQLite does not have this limitation. While this may be desired in the future, it is not necessary
+ # should not initialize if one wallet is a copy of another
+ shutil.copyfile(wallet_dir('w8'), wallet_dir('w8_copy'))
+ in_wallet_dir.append('w8_copy')
+ exp_stderr = r"BerkeleyDatabase: Can't open database w8_copy \(duplicates fileid \w+ from w8\)"
+ self.nodes[0].assert_start_raises_init_error(['-wallet=w8', '-wallet=w8_copy'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
# should not initialize if wallet file is a symlink
os.symlink('w8', wallet_dir('w8_symlink'))
@@ -139,17 +173,24 @@ class MultiWalletTest(BitcoinTestFramework):
open(not_a_dir, 'a', encoding="utf8").close()
self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory')
+ self.log.info("Do not allow -upgradewallet with multiwallet")
+ self.nodes[0].assert_start_raises_init_error(['-upgradewallet'], "Error: Error parsing command line arguments: Invalid parameter -upgradewallet")
+
# if wallets/ doesn't exist, datadir should be the default wallet dir
wallet_dir2 = data_dir('walletdir')
os.rename(wallet_dir(), wallet_dir2)
- self.start_node(0, ['-nowallet', '-wallet=w4', '-wallet=w5'])
+ self.start_node(0)
+ self.nodes[0].createwallet("w4")
+ self.nodes[0].createwallet("w5")
assert_equal(set(node.listwallets()), {"w4", "w5"})
w5 = wallet("w5")
node.generatetoaddress(nblocks=1, address=w5.getnewaddress())
# now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded
os.rename(wallet_dir2, wallet_dir())
- self.restart_node(0, ['-nowallet', '-wallet=w4', '-wallet=w5', '-walletdir=' + data_dir()])
+ self.restart_node(0, ['-nowallet', '-walletdir=' + data_dir()])
+ self.nodes[0].loadwallet("w4")
+ self.nodes[0].loadwallet("w5")
assert_equal(set(node.listwallets()), {"w4", "w5"})
w5 = wallet("w5")
w5_info = w5.getwalletinfo()
@@ -157,13 +198,19 @@ class MultiWalletTest(BitcoinTestFramework):
competing_wallet_dir = os.path.join(self.options.tmpdir, 'competing_walletdir')
os.mkdir(competing_wallet_dir)
- self.restart_node(0, ['-walletdir=' + competing_wallet_dir])
- exp_stderr = r"Error: Error initializing wallet database environment \"\S+competing_walletdir\S*\"!"
+ self.restart_node(0, ['-nowallet', '-walletdir=' + competing_wallet_dir])
+ self.nodes[0].createwallet(self.default_wallet_name)
+ if self.options.descriptors:
+ exp_stderr = r"Error: SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another bitcoind?"
+ else:
+ exp_stderr = r"Error: Error initializing wallet database environment \"\S+competing_walletdir\S*\"!"
self.nodes[1].assert_start_raises_init_error(['-walletdir=' + competing_wallet_dir], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
- self.restart_node(0, extra_args)
+ self.restart_node(0)
+ for wallet_name in wallet_names:
+ self.nodes[0].loadwallet(wallet_name)
- assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), [self.default_wallet_name, os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy'])
+ assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), sorted(in_wallet_dir))
wallets = [wallet(w) for w in wallet_names]
wallet_bad = wallet("bad")
@@ -233,7 +280,7 @@ class MultiWalletTest(BitcoinTestFramework):
threads = []
for _ in range(3):
n = node.cli if self.options.usecli else get_rpc_proxy(node.url, 1, timeout=600, coveragedir=node.coverage_dir)
- t = Thread(target=test_load_unload, args=(n, wallet_names[2], ))
+ t = Thread(target=test_load_unload, args=(n, wallet_names[2]))
t.start()
threads.append(t)
for t in threads:
@@ -254,19 +301,22 @@ class MultiWalletTest(BitcoinTestFramework):
# Fail to load duplicate wallets
path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "w1", "wallet.dat")
- assert_raises_rpc_error(-4, "Wallet file verification failed. Refusing to load database. Data file '{}' is already loaded.".format(path), self.nodes[0].loadwallet, wallet_names[0])
+ if self.options.descriptors:
+ assert_raises_rpc_error(-4, "Wallet file verification failed. SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another bitcoind?", self.nodes[0].loadwallet, wallet_names[0])
+ else:
+ assert_raises_rpc_error(-4, "Wallet file verification failed. Refusing to load database. Data file '{}' is already loaded.".format(path), self.nodes[0].loadwallet, wallet_names[0])
- # Fail to load duplicate wallets by different ways (directory and filepath)
- if not self.options.descriptors:
+ # This tests the default wallet that BDB makes, so SQLite wallet doesn't need to test this
+ # Fail to load duplicate wallets by different ways (directory and filepath)
path = os.path.join(self.options.tmpdir, "node0", "regtest", "wallets", "wallet.dat")
assert_raises_rpc_error(-4, "Wallet file verification failed. Refusing to load database. Data file '{}' is already loaded.".format(path), self.nodes[0].loadwallet, 'wallet.dat')
- # Fail to load if one wallet is a copy of another
- assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
-
- # Fail to load if one wallet is a copy of another, test this twice to make sure that we don't re-introduce #14304
- assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
+ # Only BDB doesn't open duplicate wallet files. SQLite does not have this limitation. While this may be desired in the future, it is not necessary
+ # Fail to load if one wallet is a copy of another
+ assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
+ # Fail to load if one wallet is a copy of another, test this twice to make sure that we don't re-introduce #14304
+ assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
# Fail to load if wallet file is a symlink
assert_raises_rpc_error(-4, "Wallet file verification failed. Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
@@ -284,6 +334,7 @@ class MultiWalletTest(BitcoinTestFramework):
# Successfully create a wallet with a new name
loadwallet_name = self.nodes[0].createwallet('w9')
+ in_wallet_dir.append('w9')
assert_equal(loadwallet_name['name'], 'w9')
w9 = node.get_wallet_rpc('w9')
assert_equal(w9.getwalletinfo()['walletname'], 'w9')
@@ -306,12 +357,18 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "JSON value is not a string as expected", 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, "Cannot unload the requested wallet", w1.unloadwallet, "w2"),
+ assert_raises_rpc_error(-8, "RPC endpoint wallet and wallet_name parameter specify different wallets", w1.unloadwallet, "w2"),
# Successfully unload the specified wallet name
self.nodes[0].unloadwallet("w1")
assert 'w1' not in self.nodes[0].listwallets()
+ # Unload w1 again, this time providing the wallet name twice
+ self.nodes[0].loadwallet("w1")
+ assert 'w1' in self.nodes[0].listwallets()
+ w1.unloadwallet("w1")
+ assert 'w1' not in self.nodes[0].listwallets()
+
# Successfully unload the wallet referenced by the request endpoint
# Also ensure unload works during walletpassphrase timeout
w2.encryptwallet('test')
@@ -331,7 +388,7 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].listwallets(), ['w1'])
assert_equal(w1.getwalletinfo()['walletname'], 'w1')
- assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), [self.default_wallet_name, os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy', 'w9'])
+ assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), sorted(in_wallet_dir))
# Test backing up and restoring wallets
self.log.info("Test wallet backup")
@@ -365,5 +422,6 @@ class MultiWalletTest(BitcoinTestFramework):
self.nodes[0].unloadwallet(wallet)
self.nodes[1].loadwallet(wallet)
+
if __name__ == '__main__':
MultiWalletTest().main()
diff --git a/test/functional/wallet_reorgsrestore.py b/test/functional/wallet_reorgsrestore.py
index 5c24d466c3..a1d6b098ad 100755
--- a/test/functional/wallet_reorgsrestore.py
+++ b/test/functional/wallet_reorgsrestore.py
@@ -20,8 +20,6 @@ import shutil
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
- disconnect_nodes,
)
class ReorgsRestoreTest(BitcoinTestFramework):
@@ -38,9 +36,9 @@ class ReorgsRestoreTest(BitcoinTestFramework):
self.sync_blocks()
# Disconnect node1 from others to reorg its chain later
- disconnect_nodes(self.nodes[0], 1)
- disconnect_nodes(self.nodes[1], 2)
- connect_nodes(self.nodes[0], 2)
+ self.disconnect_nodes(0, 1)
+ self.disconnect_nodes(1, 2)
+ self.connect_nodes(0, 2)
# Send a tx to be unconfirmed later
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
@@ -50,7 +48,7 @@ class ReorgsRestoreTest(BitcoinTestFramework):
assert_equal(tx_before_reorg["confirmations"], 4)
# Disconnect node0 from node2 to broadcast a conflict on their respective chains
- disconnect_nodes(self.nodes[0], 2)
+ self.disconnect_nodes(0, 2)
nA = next(tx_out["vout"] for tx_out in self.nodes[0].gettransaction(txid_conflict_from)["details"] if tx_out["amount"] == Decimal("10"))
inputs = []
inputs.append({"txid": txid_conflict_from, "vout": nA})
@@ -69,7 +67,7 @@ class ReorgsRestoreTest(BitcoinTestFramework):
self.nodes[2].generate(9)
# Reconnect node0 and node2 and check that conflicted_txid is effectively conflicted
- connect_nodes(self.nodes[0], 2)
+ self.connect_nodes(0, 2)
self.sync_blocks([self.nodes[0], self.nodes[2]])
conflicted = self.nodes[0].gettransaction(conflicted_txid)
conflicting = self.nodes[0].gettransaction(conflicting_txid)
diff --git a/test/functional/wallet_resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py
index 1dcb12de08..78d88f8aa5 100755
--- a/test/functional/wallet_resendwallettransactions.py
+++ b/test/functional/wallet_resendwallettransactions.py
@@ -11,6 +11,7 @@ from test_framework.p2p import P2PTxInvStore
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
+
class ResendWalletTransactionsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
@@ -27,10 +28,10 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
txid = node.sendtoaddress(node.getnewaddress(), 1)
# Wallet rebroadcast is first scheduled 1 sec after startup (see
- # nNextResend in ResendWalletTransactions()). Sleep for just over a
- # second to be certain that it has been called before the first
+ # nNextResend in ResendWalletTransactions()). Tell scheduler to call
+ # MaybeResendWalletTxn now to initialize nNextResend before the first
# setmocktime call below.
- time.sleep(1.1)
+ node.mockscheduler(1)
# Can take a few seconds due to transaction trickling
peer_first.wait_for_broadcast([txid])
@@ -49,6 +50,7 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
block.solve()
node.submitblock(ToHex(block))
+ # Set correct m_best_block_time, which is used in ResendWalletTransactions
node.syncwithvalidationinterfacequeue()
now = int(time.time())
@@ -57,15 +59,16 @@ class ResendWalletTransactionsTest(BitcoinTestFramework):
twelve_hrs = 12 * 60 * 60
two_min = 2 * 60
node.setmocktime(now + twelve_hrs - two_min)
- time.sleep(2) # ensure enough time has passed for rebroadcast attempt to occur
+ node.mockscheduler(1) # Tell scheduler to call MaybeResendWalletTxn 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.
- node.setmocktime(now + 36 * 60 * 60)
- # Tell scheduler to call MaybeResendWalletTxn now.
- node.mockscheduler(1)
+ with node.assert_debug_log(['ResendWalletTransactions: resubmit 1 unconfirmed transactions']):
+ node.setmocktime(now + 36 * 60 * 60)
+ # Tell scheduler to call MaybeResendWalletTxn now.
+ node.mockscheduler(1)
# Give some time for trickle to occur
node.setmocktime(now + 36 * 60 * 60 + 600)
peer_second.wait_for_broadcast([txid])
diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py
index 876eb7f29e..9835c5a2af 100755
--- a/test/functional/wallet_send.py
+++ b/test/functional/wallet_send.py
@@ -5,13 +5,15 @@
"""Test the send RPC command."""
from decimal import Decimal, getcontext
+from itertools import product
+
from test_framework.authproxy import JSONRPCException
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_fee_amount,
assert_greater_than,
- assert_raises_rpc_error
+ assert_raises_rpc_error,
)
class WalletSendTest(BitcoinTestFramework):
@@ -28,8 +30,8 @@ class WalletSendTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def test_send(self, from_wallet, to_wallet=None, amount=None, data=None,
- arg_conf_target=None, arg_estimate_mode=None,
- conf_target=None, estimate_mode=None, add_to_wallet=None, psbt=None,
+ arg_conf_target=None, arg_estimate_mode=None, arg_fee_rate=None,
+ conf_target=None, estimate_mode=None, fee_rate=None, add_to_wallet=None, psbt=None,
inputs=None, add_inputs=None, change_address=None, change_position=None, change_type=None,
include_watching=None, locktime=None, lock_unspents=None, replaceable=None, subtract_fee_from_outputs=None,
expect_error=None):
@@ -62,6 +64,8 @@ class WalletSendTest(BitcoinTestFramework):
options["conf_target"] = conf_target
if estimate_mode is not None:
options["estimate_mode"] = estimate_mode
+ if fee_rate is not None:
+ options["fee_rate"] = fee_rate
if inputs is not None:
options["inputs"] = inputs
if add_inputs is not None:
@@ -89,16 +93,19 @@ class WalletSendTest(BitcoinTestFramework):
options = None
if expect_error is None:
- res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options)
+ res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, fee_rate=arg_fee_rate, options=options)
else:
try:
assert_raises_rpc_error(expect_error[0], expect_error[1], from_wallet.send,
- outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options)
+ outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, fee_rate=arg_fee_rate, options=options)
except AssertionError:
# Provide debug info if the test fails
self.log.error("Unexpected successful result:")
+ self.log.error(arg_conf_target)
+ self.log.error(arg_estimate_mode)
+ self.log.error(arg_fee_rate)
self.log.error(options)
- res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, options=options)
+ res = from_wallet.send(outputs=outputs, conf_target=arg_conf_target, estimate_mode=arg_estimate_mode, fee_rate=arg_fee_rate, options=options)
self.log.error(res)
if "txid" in res and add_to_wallet:
self.log.error("Transaction details:")
@@ -224,8 +231,10 @@ class WalletSendTest(BitcoinTestFramework):
assert_equal(self.nodes[1].decodepsbt(res1["psbt"])["fee"],
self.nodes[1].decodepsbt(res2["psbt"])["fee"])
# but not at the same time
- self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical",
- conf_target=1, estimate_mode="economical", add_to_wallet=False, expect_error=(-8,"Use either conf_target and estimate_mode or the options dictionary to control fee rate"))
+ for mode in ["unset", "economical", "conservative"]:
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=1, arg_estimate_mode="economical",
+ conf_target=1, estimate_mode=mode, add_to_wallet=False,
+ expect_error=(-8, "Pass conf_target and estimate_mode either as arguments or in the options object, but not both"))
self.log.info("Create PSBT from watch-only wallet w3, sign with w2...")
res = self.test_send(from_wallet=w3, to_wallet=w1, amount=1)
@@ -246,19 +255,63 @@ class WalletSendTest(BitcoinTestFramework):
res = w2.walletprocesspsbt(res["psbt"])
assert res["complete"]
- self.log.info("Set fee rate...")
- res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=2, estimate_mode="sat/b", add_to_wallet=False)
+ self.log.info("Test setting explicit fee rate")
+ res1 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate="1", add_to_wallet=False)
+ res2 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate="1", add_to_wallet=False)
+ assert_equal(self.nodes[1].decodepsbt(res1["psbt"])["fee"], self.nodes[1].decodepsbt(res2["psbt"])["fee"])
+
+ res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=7, add_to_wallet=False)
+ fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
+ assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00007"))
+
+ # "unset" and None are treated the same for estimate_mode
+ res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=2, estimate_mode="unset", add_to_wallet=False)
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00002"))
- self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=-1, estimate_mode="sat/b",
- expect_error=(-3, "Amount out of range"))
- # Fee rate of 0.1 satoshi per byte should throw an error
- # TODO: error should use sat/b
- self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b",
- expect_error=(-4, "Fee rate (0.00000100 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)"))
- self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.000001, estimate_mode="BTC/KB",
- expect_error=(-4, "Fee rate (0.00000100 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB)"))
+ res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=4.531, add_to_wallet=False)
+ fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
+ assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00004531"))
+
+ res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=3, add_to_wallet=False)
+ fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
+ assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00003"))
+
+ # Test that passing fee_rate as both an argument and an option raises.
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=1, fee_rate=1, add_to_wallet=False,
+ expect_error=(-8, "Pass the fee_rate either as an argument, or in the options object, but not both"))
+
+ assert_raises_rpc_error(-8, "Use fee_rate (sat/vB) instead of feeRate", w0.send, {w1.getnewaddress(): 1}, 6, "conservative", 1, {"feeRate": 0.01})
+
+ assert_raises_rpc_error(-3, "Unexpected key totalFee", w0.send, {w1.getnewaddress(): 1}, 6, "conservative", 1, {"totalFee": 0.01})
+
+ for target, mode in product([-1, 0, 1009], ["economical", "conservative"]):
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode,
+ expect_error=(-8, "Invalid conf_target, must be between 1 and 1008")) # max value of 1008 per src/policy/fees.h
+ msg = 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"'
+ for target, mode in product([-1, 0], ["btc/kb", "sat/b"]):
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=target, estimate_mode=mode, expect_error=(-8, msg))
+ for mode in ["", "foo", Decimal("3.141592")]:
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode=mode, expect_error=(-8, msg))
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.1, arg_estimate_mode=mode, expect_error=(-8, msg))
+ assert_raises_rpc_error(-8, msg, w0.send, {w1.getnewaddress(): 1}, 0.1, mode)
+
+ for mode in ["economical", "conservative", "btc/kb", "sat/b"]:
+ self.log.debug("{}".format(mode))
+ for k, v in {"string": "true", "object": {"foo": "bar"}}.items():
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode,
+ expect_error=(-3, "Expected type number for conf_target, got {}".format(k)))
+
+ # Test setting explicit fee rate just below the minimum and at zero.
+ self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 0.99999999 is passed")
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0.99999999,
+ expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0.99999999,
+ expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0,
+ expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
+ self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0,
+ expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
# TODO: Return hex if fee rate is below -maxmempool
# res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False)
@@ -316,6 +369,7 @@ class WalletSendTest(BitcoinTestFramework):
res = self.nodes[0].sendrawtransaction(hex)
self.nodes[0].generate(1)
assert_equal(self.nodes[0].gettransaction(txid)["confirmations"], 1)
+ self.sync_all()
self.log.info("Lock unspents...")
utxo1 = w0.listunspent()[0]
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index 33a2a9411e..bdbbb3e530 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -8,8 +8,6 @@ import io
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
- disconnect_nodes,
)
from test_framework.messages import CTransaction, COIN
@@ -30,7 +28,7 @@ class TxnMallTest(BitcoinTestFramework):
def setup_network(self):
# Start with split network:
super().setup_network()
- disconnect_nodes(self.nodes[1], 2)
+ self.disconnect_nodes(1, 2)
def run_test(self):
if self.options.segwit:
@@ -118,7 +116,7 @@ class TxnMallTest(BitcoinTestFramework):
self.nodes[2].generate(1)
# Reconnect the split network, and sync chain:
- connect_nodes(self.nodes[1], 2)
+ self.connect_nodes(1, 2)
self.nodes[2].sendrawtransaction(node0_tx2["hex"])
self.nodes[2].sendrawtransaction(tx2["hex"])
self.nodes[2].generate(1) # Mine another block to make sure we sync
diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index cac58aeaf2..42de131354 100755
--- a/test/functional/wallet_txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -8,8 +8,6 @@ from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- connect_nodes,
- disconnect_nodes,
find_output,
)
@@ -28,7 +26,7 @@ class TxnMallTest(BitcoinTestFramework):
def setup_network(self):
# Start with split network:
super().setup_network()
- disconnect_nodes(self.nodes[1], 2)
+ self.disconnect_nodes(1, 2)
def run_test(self):
# All nodes should start with 1,250 BTC:
@@ -116,7 +114,7 @@ class TxnMallTest(BitcoinTestFramework):
self.nodes[2].generate(1)
# Reconnect the split network, and sync chain:
- connect_nodes(self.nodes[1], 2)
+ self.connect_nodes(1, 2)
self.nodes[2].generate(1) # Mine another block to make sure we sync
self.sync_blocks()
assert_equal(self.nodes[0].gettransaction(doublespend_txid)["confirmations"], 2)
diff --git a/test/functional/wallet_upgradewallet.py b/test/functional/wallet_upgradewallet.py
index 446a601aee..d0bb6135a8 100755
--- a/test/functional/wallet_upgradewallet.py
+++ b/test/functional/wallet_upgradewallet.py
@@ -13,23 +13,45 @@ Only v0.15.2 and v0.16.3 are required by this test. The others are used in featu
import os
import shutil
+import struct
+from io import BytesIO
+
+from test_framework.bdb import dump_bdb_kv
+from test_framework.messages import deser_compact_size, deser_string
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
- assert_greater_than,
assert_is_hex_string,
+ sha256sum_file,
)
+UPGRADED_KEYMETA_VERSION = 12
+
+def deser_keymeta(f):
+ ver, create_time = struct.unpack('<Iq', f.read(12))
+ kp_str = deser_string(f)
+ seed_id = f.read(20)
+ fpr = f.read(4)
+ path_len = 0
+ path = []
+ has_key_orig = False
+ if ver == UPGRADED_KEYMETA_VERSION:
+ path_len = deser_compact_size(f)
+ for i in range(0, path_len):
+ path.append(struct.unpack('<I', f.read(4))[0])
+ has_key_orig = bool(f.read(1))
+ return ver, create_time, kp_str, seed_id, fpr, path_len, path, has_key_orig
+
class UpgradeWalletTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
self.extra_args = [
- ["-addresstype=bech32"], # current wallet version
- ["-usehd=1"], # v0.16.3 wallet
- ["-usehd=0"] # v0.15.2 wallet
+ ["-addresstype=bech32", "-keypool=2"], # current wallet version
+ ["-usehd=1", "-keypool=2"], # v0.16.3 wallet
+ ["-usehd=0", "-keypool=2"] # v0.15.2 wallet
]
self.wallet_names = [self.default_wallet_name, None, None]
@@ -68,6 +90,32 @@ class UpgradeWalletTest(BitcoinTestFramework):
v16_3_node.submitblock(b)
assert_equal(v16_3_node.getblockcount(), to_height)
+ def test_upgradewallet(self, wallet, previous_version, requested_version=None, expected_version=None):
+ unchanged = expected_version == previous_version
+ new_version = previous_version if unchanged else expected_version if expected_version else requested_version
+ assert_equal(wallet.getwalletinfo()["walletversion"], previous_version)
+ assert_equal(wallet.upgradewallet(requested_version),
+ {
+ "wallet_name": "",
+ "previous_version": previous_version,
+ "current_version": new_version,
+ "result": "Already at latest version. Wallet version unchanged." if unchanged else "Wallet upgraded successfully from version {} to version {}.".format(previous_version, new_version),
+ }
+ )
+ assert_equal(wallet.getwalletinfo()["walletversion"], new_version)
+
+ def test_upgradewallet_error(self, wallet, previous_version, requested_version, msg):
+ assert_equal(wallet.getwalletinfo()["walletversion"], previous_version)
+ assert_equal(wallet.upgradewallet(requested_version),
+ {
+ "wallet_name": "",
+ "previous_version": previous_version,
+ "current_version": previous_version,
+ "error": msg,
+ }
+ )
+ assert_equal(wallet.getwalletinfo()["walletversion"], previous_version)
+
def run_test(self):
self.nodes[0].generatetoaddress(101, self.nodes[0].getnewaddress())
self.dumb_sync_blocks()
@@ -87,55 +135,222 @@ class UpgradeWalletTest(BitcoinTestFramework):
self.log.info("Test upgradewallet RPC...")
# Prepare for copying of the older wallet
- node_master_wallet_dir = os.path.join(node_master.datadir, "regtest/wallets")
+ node_master_wallet_dir = os.path.join(node_master.datadir, "regtest/wallets", self.default_wallet_name)
+ node_master_wallet = os.path.join(node_master_wallet_dir, self.default_wallet_name, self.wallet_data_filename)
v16_3_wallet = os.path.join(v16_3_node.datadir, "regtest/wallets/wallet.dat")
v15_2_wallet = os.path.join(v15_2_node.datadir, "regtest/wallet.dat")
+ split_hd_wallet = os.path.join(v15_2_node.datadir, "regtest/splithd")
self.stop_nodes()
- # Copy the 0.16.3 wallet to the last Bitcoin Core version and open it:
- shutil.rmtree(node_master_wallet_dir)
- os.mkdir(node_master_wallet_dir)
- shutil.copy(
- v16_3_wallet,
- node_master_wallet_dir
- )
- self.restart_node(0, ['-nowallet'])
- node_master.loadwallet('')
+ # Make split hd wallet
+ self.start_node(2, ['-usehd=1', '-keypool=2', '-wallet=splithd'])
+ self.stop_node(2)
+
+ def copy_v16():
+ node_master.get_wallet_rpc(self.default_wallet_name).unloadwallet()
+ # Copy the 0.16.3 wallet to the last Bitcoin Core version and open it:
+ shutil.rmtree(node_master_wallet_dir)
+ os.mkdir(node_master_wallet_dir)
+ shutil.copy(
+ v16_3_wallet,
+ node_master_wallet_dir
+ )
+ node_master.loadwallet(self.default_wallet_name)
+
+ def copy_non_hd():
+ node_master.get_wallet_rpc(self.default_wallet_name).unloadwallet()
+ # Copy the 0.15.2 non hd wallet to the last Bitcoin Core version and open it:
+ shutil.rmtree(node_master_wallet_dir)
+ os.mkdir(node_master_wallet_dir)
+ shutil.copy(
+ v15_2_wallet,
+ node_master_wallet_dir
+ )
+ node_master.loadwallet(self.default_wallet_name)
- wallet = node_master.get_wallet_rpc('')
- old_version = wallet.getwalletinfo()["walletversion"]
+ def copy_split_hd():
+ node_master.get_wallet_rpc(self.default_wallet_name).unloadwallet()
+ # Copy the 0.15.2 split hd wallet to the last Bitcoin Core version and open it:
+ shutil.rmtree(node_master_wallet_dir)
+ os.mkdir(node_master_wallet_dir)
+ shutil.copy(
+ split_hd_wallet,
+ os.path.join(node_master_wallet_dir, 'wallet.dat')
+ )
+ node_master.loadwallet(self.default_wallet_name)
- # calling upgradewallet without version arguments
- # should return nothing if successful
- assert_equal(wallet.upgradewallet(), "")
- new_version = wallet.getwalletinfo()["walletversion"]
- # upgraded wallet version should be greater than older one
- assert_greater_than(new_version, old_version)
+ self.restart_node(0)
+ copy_v16()
+ wallet = node_master.get_wallet_rpc(self.default_wallet_name)
+ self.log.info("Test upgradewallet without a version argument")
+ self.test_upgradewallet(wallet, previous_version=159900, expected_version=169900)
# wallet should still contain the same balance
assert_equal(wallet.getbalance(), v16_3_balance)
- self.stop_node(0)
- # Copy the 0.15.2 wallet to the last Bitcoin Core version and open it:
- shutil.rmtree(node_master_wallet_dir)
- os.mkdir(node_master_wallet_dir)
- shutil.copy(
- v15_2_wallet,
- node_master_wallet_dir
- )
- self.restart_node(0, ['-nowallet'])
- node_master.loadwallet('')
-
- wallet = node_master.get_wallet_rpc('')
+ copy_non_hd()
+ wallet = node_master.get_wallet_rpc(self.default_wallet_name)
# should have no master key hash before conversion
assert_equal('hdseedid' in wallet.getwalletinfo(), False)
- # calling upgradewallet with explicit version number
- # should return nothing if successful
- assert_equal(wallet.upgradewallet(169900), "")
- new_version = wallet.getwalletinfo()["walletversion"]
- # upgraded wallet should have version 169900
- assert_equal(new_version, 169900)
+ self.log.info("Test upgradewallet with explicit version number")
+ self.test_upgradewallet(wallet, previous_version=60000, requested_version=169900)
# after conversion master key hash should be present
assert_is_hex_string(wallet.getwalletinfo()['hdseedid'])
+ self.log.info("Intermediary versions don't effect anything")
+ copy_non_hd()
+ # Wallet starts with 60000
+ assert_equal(60000, wallet.getwalletinfo()['walletversion'])
+ wallet.unloadwallet()
+ before_checksum = sha256sum_file(node_master_wallet)
+ node_master.loadwallet('')
+ # Test an "upgrade" from 60000 to 129999 has no effect, as the next version is 130000
+ self.test_upgradewallet(wallet, previous_version=60000, requested_version=129999, expected_version=60000)
+ wallet.unloadwallet()
+ assert_equal(before_checksum, sha256sum_file(node_master_wallet))
+ node_master.loadwallet('')
+
+ self.log.info('Wallets cannot be downgraded')
+ copy_non_hd()
+ self.test_upgradewallet_error(wallet, previous_version=60000, requested_version=40000,
+ msg="Cannot downgrade wallet from version 60000 to version 40000. Wallet version unchanged.")
+ wallet.unloadwallet()
+ assert_equal(before_checksum, sha256sum_file(node_master_wallet))
+ node_master.loadwallet('')
+
+ self.log.info('Can upgrade to HD')
+ # Inspect the old wallet and make sure there is no hdchain
+ orig_kvs = dump_bdb_kv(node_master_wallet)
+ assert b'\x07hdchain' not in orig_kvs
+ # Upgrade to HD, no split
+ self.test_upgradewallet(wallet, previous_version=60000, requested_version=130000)
+ # Check that there is now a hd chain and it is version 1, no internal chain counter
+ new_kvs = dump_bdb_kv(node_master_wallet)
+ assert b'\x07hdchain' in new_kvs
+ hd_chain = new_kvs[b'\x07hdchain']
+ assert_equal(28, len(hd_chain))
+ hd_chain_version, external_counter, seed_id = struct.unpack('<iI20s', hd_chain)
+ assert_equal(1, hd_chain_version)
+ seed_id = bytearray(seed_id)
+ seed_id.reverse()
+ old_kvs = new_kvs
+ # First 2 keys should still be non-HD
+ for i in range(0, 2):
+ info = wallet.getaddressinfo(wallet.getnewaddress())
+ assert 'hdkeypath' not in info
+ assert 'hdseedid' not in info
+ # Next key should be HD
+ info = wallet.getaddressinfo(wallet.getnewaddress())
+ assert_equal(seed_id.hex(), info['hdseedid'])
+ assert_equal('m/0\'/0\'/0\'', info['hdkeypath'])
+ prev_seed_id = info['hdseedid']
+ # Change key should be the same keypool
+ info = wallet.getaddressinfo(wallet.getrawchangeaddress())
+ assert_equal(prev_seed_id, info['hdseedid'])
+ assert_equal('m/0\'/0\'/1\'', info['hdkeypath'])
+
+ self.log.info('Cannot upgrade to HD Split, needs Pre Split Keypool')
+ for version in [139900, 159900, 169899]:
+ self.test_upgradewallet_error(wallet, previous_version=130000, requested_version=version,
+ msg="Cannot upgrade a non HD split wallet from version {} to version {} without upgrading to "
+ "support pre-split keypool. Please use version 169900 or no version specified.".format(130000, version))
+
+ self.log.info('Upgrade HD to HD chain split')
+ self.test_upgradewallet(wallet, previous_version=130000, requested_version=169900)
+ # Check that the hdchain updated correctly
+ new_kvs = dump_bdb_kv(node_master_wallet)
+ hd_chain = new_kvs[b'\x07hdchain']
+ assert_equal(32, len(hd_chain))
+ hd_chain_version, external_counter, seed_id, internal_counter = struct.unpack('<iI20sI', hd_chain)
+ assert_equal(2, hd_chain_version)
+ assert_equal(0, internal_counter)
+ seed_id = bytearray(seed_id)
+ seed_id.reverse()
+ assert_equal(seed_id.hex(), prev_seed_id)
+ # Next change address is the same keypool
+ info = wallet.getaddressinfo(wallet.getrawchangeaddress())
+ assert_equal(prev_seed_id, info['hdseedid'])
+ assert_equal('m/0\'/0\'/2\'', info['hdkeypath'])
+ # Next change address is the new keypool
+ info = wallet.getaddressinfo(wallet.getrawchangeaddress())
+ assert_equal(prev_seed_id, info['hdseedid'])
+ assert_equal('m/0\'/1\'/0\'', info['hdkeypath'])
+ # External addresses use the same keypool
+ info = wallet.getaddressinfo(wallet.getnewaddress())
+ assert_equal(prev_seed_id, info['hdseedid'])
+ assert_equal('m/0\'/0\'/3\'', info['hdkeypath'])
+
+ self.log.info('Upgrade non-HD to HD chain split')
+ copy_non_hd()
+ self.test_upgradewallet(wallet, previous_version=60000, requested_version=169900)
+ # Check that the hdchain updated correctly
+ new_kvs = dump_bdb_kv(node_master_wallet)
+ hd_chain = new_kvs[b'\x07hdchain']
+ assert_equal(32, len(hd_chain))
+ hd_chain_version, external_counter, seed_id, internal_counter = struct.unpack('<iI20sI', hd_chain)
+ assert_equal(2, hd_chain_version)
+ assert_equal(2, internal_counter)
+ # Drain the keypool by fetching one external key and one change key. Should still be the same keypool
+ info = wallet.getaddressinfo(wallet.getnewaddress())
+ assert 'hdseedid' not in info
+ assert 'hdkeypath' not in info
+ info = wallet.getaddressinfo(wallet.getrawchangeaddress())
+ assert 'hdseedid' not in info
+ assert 'hdkeypath' not in info
+ # The next addresses are HD and should be on different HD chains
+ info = wallet.getaddressinfo(wallet.getnewaddress())
+ ext_id = info['hdseedid']
+ assert_equal('m/0\'/0\'/0\'', info['hdkeypath'])
+ info = wallet.getaddressinfo(wallet.getrawchangeaddress())
+ assert_equal(ext_id, info['hdseedid'])
+ assert_equal('m/0\'/1\'/0\'', info['hdkeypath'])
+
+ self.log.info('KeyMetadata should upgrade when loading into master')
+ copy_v16()
+ old_kvs = dump_bdb_kv(v16_3_wallet)
+ new_kvs = dump_bdb_kv(node_master_wallet)
+ for k, old_v in old_kvs.items():
+ if k.startswith(b'\x07keymeta'):
+ new_ver, new_create_time, new_kp_str, new_seed_id, new_fpr, new_path_len, new_path, new_has_key_orig = deser_keymeta(BytesIO(new_kvs[k]))
+ old_ver, old_create_time, old_kp_str, old_seed_id, old_fpr, old_path_len, old_path, old_has_key_orig = deser_keymeta(BytesIO(old_v))
+ assert_equal(10, old_ver)
+ if old_kp_str == b"": # imported things that don't have keymeta (i.e. imported coinbase privkeys) won't be upgraded
+ assert_equal(new_kvs[k], old_v)
+ continue
+ assert_equal(12, new_ver)
+ assert_equal(new_create_time, old_create_time)
+ assert_equal(new_kp_str, old_kp_str)
+ assert_equal(new_seed_id, old_seed_id)
+ assert_equal(0, old_path_len)
+ assert_equal(new_path_len, len(new_path))
+ assert_equal([], old_path)
+ assert_equal(False, old_has_key_orig)
+ assert_equal(True, new_has_key_orig)
+
+ # Check that the path is right
+ built_path = []
+ for s in new_kp_str.decode().split('/')[1:]:
+ h = 0
+ if s[-1] == '\'':
+ s = s[:-1]
+ h = 0x80000000
+ p = int(s) | h
+ built_path.append(p)
+ assert_equal(new_path, built_path)
+
+ self.log.info('Upgrading to NO_DEFAULT_KEY should not remove the defaultkey')
+ copy_split_hd()
+ # Check the wallet has a default key initially
+ old_kvs = dump_bdb_kv(node_master_wallet)
+ defaultkey = old_kvs[b'\x0adefaultkey']
+ self.log.info("Upgrade the wallet. Should still have the same default key.")
+ self.test_upgradewallet(wallet, previous_version=139900, requested_version=159900)
+ new_kvs = dump_bdb_kv(node_master_wallet)
+ up_defaultkey = new_kvs[b'\x0adefaultkey']
+ assert_equal(defaultkey, up_defaultkey)
+ # 0.16.3 doesn't have a default key
+ v16_3_kvs = dump_bdb_kv(v16_3_wallet)
+ assert b'\x0adefaultkey' not in v16_3_kvs
+
+
if __name__ == '__main__':
UpgradeWalletTest().main()
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index c7895edbcc..3a2cefbe2b 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -83,7 +83,7 @@ def main():
sys.exit(1)
# Build list of tests
- test_list_all = parse_test_list(makefile=os.path.join(config["environment"]["SRCDIR"], 'src', 'Makefile.test.include'))
+ test_list_all = parse_test_list(fuzz_bin=os.path.join(config["environment"]["BUILDDIR"], 'src', 'test', 'fuzz', 'fuzz'))
if not test_list_all:
logging.error("No fuzz targets found")
@@ -126,9 +126,12 @@ def main():
try:
help_output = subprocess.run(
args=[
- os.path.join(config["environment"]["BUILDDIR"], 'src', 'test', 'fuzz', test_list_selection[0]),
+ os.path.join(config["environment"]["BUILDDIR"], 'src', 'test', 'fuzz', 'fuzz'),
'-help=1',
],
+ env={
+ 'FUZZ': test_list_selection[0]
+ },
timeout=20,
check=True,
stderr=subprocess.PIPE,
@@ -177,24 +180,30 @@ def generate_corpus_seeds(*, fuzz_pool, build_dir, seed_dir, targets):
"""
logging.info("Generating corpus seeds to {}".format(seed_dir))
- def job(command):
+ def job(command, t):
logging.debug("Running '{}'\n".format(" ".join(command)))
logging.debug("Command '{}' output:\n'{}'\n".format(
' '.join(command),
- subprocess.run(command, check=True, stderr=subprocess.PIPE,
- universal_newlines=True).stderr
- ))
+ subprocess.run(
+ command,
+ env={
+ 'FUZZ': t
+ },
+ check=True,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ ).stderr))
futures = []
for target in targets:
target_seed_dir = os.path.join(seed_dir, target)
os.makedirs(target_seed_dir, exist_ok=True)
command = [
- os.path.join(build_dir, "src", "test", "fuzz", target),
+ os.path.join(build_dir, 'src', 'test', 'fuzz', 'fuzz'),
"-runs=100000",
target_seed_dir,
]
- futures.append(fuzz_pool.submit(job, command))
+ futures.append(fuzz_pool.submit(job, command, target))
for future in as_completed(futures):
future.result()
@@ -205,7 +214,7 @@ def merge_inputs(*, fuzz_pool, corpus, test_list, build_dir, merge_dir):
jobs = []
for t in test_list:
args = [
- os.path.join(build_dir, 'src', 'test', 'fuzz', t),
+ os.path.join(build_dir, 'src', 'test', 'fuzz', 'fuzz'),
'-merge=1',
'-use_value_profile=1', # Also done by oss-fuzz https://github.com/google/oss-fuzz/issues/1406#issuecomment-387790487
os.path.join(corpus, t),
@@ -216,7 +225,15 @@ def merge_inputs(*, fuzz_pool, corpus, test_list, build_dir, merge_dir):
def job(t, args):
output = 'Run {} with args {}\n'.format(t, " ".join(args))
- output += subprocess.run(args, check=True, stderr=subprocess.PIPE, universal_newlines=True).stderr
+ output += subprocess.run(
+ args,
+ env={
+ 'FUZZ': t
+ },
+ check=True,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ ).stderr
logging.debug(output)
jobs.append(fuzz_pool.submit(job, t, args))
@@ -231,7 +248,7 @@ def run_once(*, fuzz_pool, corpus, test_list, build_dir, use_valgrind):
corpus_path = os.path.join(corpus, t)
os.makedirs(corpus_path, exist_ok=True)
args = [
- os.path.join(build_dir, 'src', 'test', 'fuzz', t),
+ os.path.join(build_dir, 'src', 'test', 'fuzz', 'fuzz'),
'-runs=1',
corpus_path,
]
@@ -240,7 +257,7 @@ def run_once(*, fuzz_pool, corpus, test_list, build_dir, use_valgrind):
def job(t, args):
output = 'Run {} with args {}'.format(t, args)
- result = subprocess.run(args, stderr=subprocess.PIPE, universal_newlines=True)
+ result = subprocess.run(args, env={'FUZZ': t}, stderr=subprocess.PIPE, universal_newlines=True)
output += result.stderr
return output, result
@@ -260,20 +277,16 @@ def run_once(*, fuzz_pool, corpus, test_list, build_dir, use_valgrind):
sys.exit(1)
-def parse_test_list(makefile):
- with open(makefile, encoding='utf-8') as makefile_test:
- test_list_all = []
- read_targets = False
- for line in makefile_test.readlines():
- line = line.strip().replace('test/fuzz/', '').replace(' \\', '')
- if read_targets:
- if not line:
- break
- test_list_all.append(line)
- continue
-
- if line == 'FUZZ_TARGETS =':
- read_targets = True
+def parse_test_list(*, fuzz_bin):
+ test_list_all = subprocess.run(
+ fuzz_bin,
+ env={
+ 'PRINT_ALL_FUZZ_TARGETS_AND_ABORT': ''
+ },
+ stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL,
+ universal_newlines=True,
+ ).stdout.splitlines()
return test_list_all
diff --git a/test/lint/README.md b/test/lint/README.md
index d15c061288..7e06308347 100644
--- a/test/lint/README.md
+++ b/test/lint/README.md
@@ -15,7 +15,16 @@ git-subtree-check.sh
Run this script from the root of the repository to verify that a subtree matches the contents of
the commit it claims to have been updated to.
-To use, make sure that you have fetched the upstream repository branch in which the subtree is
+```
+Usage: test/lint/git-subtree-check.sh [-r] DIR [COMMIT]
+ test/lint/git-subtree-check.sh -?
+```
+
+- `DIR` is the prefix within the repository to check.
+- `COMMIT` is the commit to check, if it is not provided, HEAD will be used.
+- `-r` checks that subtree commit is present in repository.
+
+To do a full check with `-r`, make sure that you have fetched the upstream repository branch in which the subtree is
maintained:
* for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master)
* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork)
@@ -29,10 +38,6 @@ To do so, add the upstream repository as remote:
git remote add --fetch secp256k1 https://github.com/bitcoin-core/secp256k1.git
```
-Usage: `git-subtree-check.sh DIR (COMMIT)`
-
-`COMMIT` may be omitted, in which case `HEAD` is used.
-
lint-all.sh
===========
Calls other scripts with the `lint-` prefix.
diff --git a/test/lint/extended-lint-cppcheck.sh b/test/lint/extended-lint-cppcheck.sh
index 20021d8605..b2ed811cda 100755
--- a/test/lint/extended-lint-cppcheck.sh
+++ b/test/lint/extended-lint-cppcheck.sh
@@ -30,6 +30,7 @@ IGNORED_WARNINGS=(
"src/protocol.h:.* Class 'CMessageHeader' has a constructor with 1 argument that is not explicit."
"src/qt/guiutil.h:.* Class 'ItemDelegate' has a constructor with 1 argument that is not explicit."
"src/rpc/util.h:.* Struct 'RPCResults' has a constructor with 1 argument that is not explicit."
+ "src/rpc/util.h:.* Struct 'UniValueType' has a constructor with 1 argument that is not explicit."
"src/rpc/util.h:.* style: Struct 'UniValueType' has a constructor with 1 argument that is not explicit."
"src/script/descriptor.cpp:.* Class 'AddressDescriptor' has a constructor with 1 argument that is not explicit."
"src/script/descriptor.cpp:.* Class 'ComboDescriptor' has a constructor with 1 argument that is not explicit."
@@ -42,6 +43,11 @@ IGNORED_WARNINGS=(
"src/script/descriptor.cpp:.* Class 'WSHDescriptor' has a constructor with 1 argument that is not explicit."
"src/script/script.h:.* Class 'CScript' has a constructor with 1 argument that is not explicit."
"src/script/standard.h:.* Class 'CScriptID' has a constructor with 1 argument that is not explicit."
+ "src/span.h:.* Class 'Span < const CRPCCommand >' has a constructor with 1 argument that is not explicit."
+ "src/span.h:.* Class 'Span < const char >' has a constructor with 1 argument that is not explicit."
+ "src/span.h:.* Class 'Span < const std :: vector <unsigned char > >' has a constructor with 1 argument that is not explicit."
+ "src/span.h:.* Class 'Span < const uint8_t >' has a constructor with 1 argument that is not explicit."
+ "src/span.h:.* Class 'Span' has a constructor with 1 argument that is not explicit."
"src/support/allocators/secure.h:.* Struct 'secure_allocator < char >' has a constructor with 1 argument that is not explicit."
"src/support/allocators/secure.h:.* Struct 'secure_allocator < RNGState >' has a constructor with 1 argument that is not explicit."
"src/support/allocators/secure.h:.* Struct 'secure_allocator < unsigned char >' has a constructor with 1 argument that is not explicit."
@@ -49,6 +55,9 @@ IGNORED_WARNINGS=(
"src/test/checkqueue_tests.cpp:.* Struct 'FailingCheck' has a constructor with 1 argument that is not explicit."
"src/test/checkqueue_tests.cpp:.* Struct 'MemoryCheck' has a constructor with 1 argument that is not explicit."
"src/test/checkqueue_tests.cpp:.* Struct 'UniqueCheck' has a constructor with 1 argument that is not explicit."
+ "src/test/fuzz/util.h:.* Class 'FuzzedFileProvider' has a constructor with 1 argument that is not explicit."
+ "src/test/fuzz/util.h:.* Class 'FuzzedAutoFileProvider' has a constructor with 1 argument that is not explicit."
+ "src/util/ref.h:.* Class 'Ref' has a constructor with 1 argument that is not explicit."
"src/wallet/db.h:.* Class 'BerkeleyEnvironment' has a constructor with 1 argument that is not explicit."
)
@@ -66,7 +75,7 @@ function join_array {
ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}")
IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}")
WARNINGS=$(git ls-files -- "*.cpp" "*.h" ":(exclude)src/leveldb/" ":(exclude)src/crc32c/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" | \
- xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++11 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCLIENT_VERSION_REVISION -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \
+ xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++17 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \
grep -E "${ENABLED_CHECKS_REGEXP}" | \
grep -vE "${IGNORED_WARNINGS_REGEXP}")
if [[ ${WARNINGS} != "" ]]; then
diff --git a/test/lint/git-subtree-check.sh b/test/lint/git-subtree-check.sh
index 5a0500df25..46aa6e7157 100755
--- a/test/lint/git-subtree-check.sh
+++ b/test/lint/git-subtree-check.sh
@@ -4,6 +4,39 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
export LC_ALL=C
+
+check_remote=0
+while getopts "?hr" opt; do
+ case $opt in
+ '?' | h)
+ echo "Usage: $0 [-r] DIR [COMMIT]"
+ echo " $0 -?"
+ echo ""
+ echo "Checks that a certain prefix is pure subtree, and optionally whether the"
+ echo "referenced commit is present in any fetched remote."
+ echo ""
+ echo "DIR is the prefix within the repository to check."
+ echo "COMMIT is the commit to check, if it is not provided, HEAD will be used."
+ echo ""
+ echo "-r Check that subtree commit is present in repository."
+ echo " To do this check, fetch the subtreed remote first. Example:"
+ echo ""
+ echo " git fetch https://github.com/bitcoin-core/secp256k1.git"
+ echo " test/lint/git-subtree-check.sh -r src/secp256k1"
+ exit 1
+ ;;
+ r)
+ check_remote=1
+ ;;
+ esac
+done
+shift $((OPTIND-1))
+
+if [ -z "$1" ]; then
+ echo "Need to provide a DIR, see $0 -?"
+ exit 1
+fi
+
# Strip trailing / from directory path (in case it was added by autocomplete)
DIR="${1%/}"
COMMIT="$2"
@@ -79,18 +112,20 @@ if [ "$tree_actual_tree" != "$tree_commit" ]; then
exit 1
fi
-# get the tree in the subtree commit referred to
-if [ "d$(git cat-file -t $rev 2>/dev/null)" != dcommit ]; then
- echo "subtree commit $rev unavailable: cannot compare. Did you add and fetch the remote?" >&2
- exit
-fi
-tree_subtree=$(git show -s --format="%T" $rev)
-echo "$DIR in $COMMIT was last updated to upstream commit $rev (tree $tree_subtree)"
+if [ "$check_remote" != "0" ]; then
+ # get the tree in the subtree commit referred to
+ if [ "d$(git cat-file -t $rev 2>/dev/null)" != dcommit ]; then
+ echo "subtree commit $rev unavailable: cannot compare. Did you add and fetch the remote?" >&2
+ exit 1
+ fi
+ tree_subtree=$(git show -s --format="%T" $rev)
+ echo "$DIR in $COMMIT was last updated to upstream commit $rev (tree $tree_subtree)"
-# ... and compare the actual tree with it
-if [ "$tree_actual_tree" != "$tree_subtree" ]; then
- echo "FAIL: subtree update commit differs from upstream tree!" >&2
- exit 1
+ # ... and compare the actual tree with it
+ if [ "$tree_actual_tree" != "$tree_subtree" ]; then
+ echo "FAIL: subtree update commit differs from upstream tree!" >&2
+ exit 1
+ fi
fi
echo "GOOD"
diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh
index 6bd02d45ac..c4ad00e954 100755
--- a/test/lint/lint-circular-dependencies.sh
+++ b/test/lint/lint-circular-dependencies.sh
@@ -20,7 +20,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
"txmempool -> validation -> txmempool"
"wallet/fees -> wallet/wallet -> wallet/fees"
"wallet/wallet -> wallet/walletdb -> wallet/wallet"
- "policy/fees -> txmempool -> validation -> policy/fees"
)
EXIT_CODE=0
diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh
index 72e8ef7c7d..4fc130497b 100755
--- a/test/lint/lint-python.sh
+++ b/test/lint/lint-python.sh
@@ -55,6 +55,7 @@ enabled=(
F621 # too many expressions in an assignment with star-unpacking
F622 # two or more starred expressions in an assignment (a, *b, *c = d)
F631 # assertion test is a tuple, which are always True
+ F632 # use ==/!= to compare str, bytes, and int literals
F701 # a break statement outside of a while or for loop
F702 # a continue statement outside of a while or for loop
F703 # a continue statement in a finally block in a loop
diff --git a/test/lint/lint-rpc-help.sh b/test/lint/lint-rpc-help.sh
deleted file mode 100755
index faac5d43e2..0000000000
--- a/test/lint/lint-rpc-help.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright (c) 2018 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Check that all RPC help texts are generated by RPCHelpMan.
-
-export LC_ALL=C
-
-EXIT_CODE=0
-
-# Assume that all multiline strings passed into a runtime_error are help texts.
-# This is potentially fragile, but the linter is only temporary and can safely
-# be removed early 2019.
-
-non_autogenerated_help=$(grep --perl-regexp --null-data --only-matching 'runtime_error\(\n\s*".*\\n"\n' $(git ls-files -- "*.cpp"))
-if [[ ${non_autogenerated_help} != "" ]]; then
- echo "Must use RPCHelpMan to generate the help for the following RPC methods:"
- echo "${non_autogenerated_help}"
- echo
- EXIT_CODE=1
-fi
-exit ${EXIT_CODE}
diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh
index 9a26cd9c02..351b65dea6 100755
--- a/test/lint/lint-shell.sh
+++ b/test/lint/lint-shell.sh
@@ -36,7 +36,8 @@ fi
SHELLCHECK_CMD=(shellcheck --external-sources --check-sourced)
EXCLUDE="--exclude=$(IFS=','; echo "${disabled[*]}")"
-if ! "${SHELLCHECK_CMD[@]}" "$EXCLUDE" $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|univalue)/'); then
+SOURCED_FILES=$(git ls-files | xargs gawk '/^# shellcheck shell=/ {print FILENAME} {nextfile}') # Check shellcheck directive used for sourced files
+if ! "${SHELLCHECK_CMD[@]}" "$EXCLUDE" $SOURCED_FILES $(git ls-files -- '*.sh' | grep -vE 'src/(leveldb|secp256k1|univalue)/'); then
EXIT_CODE=1
fi
diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan
index 625085c55b..986e096056 100644
--- a/test/sanitizer_suppressions/tsan
+++ b/test/sanitizer_suppressions/tsan
@@ -32,7 +32,6 @@ deadlock:CConnman::ForNode
deadlock:CConnman::GetNodeStats
deadlock:CChainState::ConnectTip
deadlock:UpdateTip
-deadlock:wallet_tests::CreateWalletFromFile
# WalletBatch (unidentified deadlock)
deadlock:WalletBatch
@@ -47,3 +46,4 @@ deadlock:src/qt/test/*
# External libraries
deadlock:libdb
race:libzmq
+race:epoll_ctl # https://github.com/bitcoin/bitcoin/pull/20218
diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan
index 75257d886b..291aab0a4a 100644
--- a/test/sanitizer_suppressions/ubsan
+++ b/test/sanitizer_suppressions/ubsan
@@ -1,8 +1,3 @@
-# -fsanitize=undefined suppressions
-# =================================
-float-divide-by-zero:validation.cpp
-float-divide-by-zero:wallet/wallet.cpp
-
# -fsanitize=integer suppressions
# ===============================
# Unsigned integer overflow occurs when the result of an unsigned integer
@@ -11,6 +6,7 @@ float-divide-by-zero:wallet/wallet.cpp
# contains files in which we expect unsigned integer overflows to occur. The
# list is used to suppress -fsanitize=integer warnings when running our CI UBSan
# job.
+unsigned-integer-overflow:*/include/c++/*/bits/basic_string.tcc
unsigned-integer-overflow:arith_uint256.h
unsigned-integer-overflow:basic_string.h
unsigned-integer-overflow:bench/bench.h
diff --git a/test/util/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json
index 99cd4ab695..0a9846b4be 100644
--- a/test/util/data/bitcoin-util-test.json
+++ b/test/util/data/bitcoin-util-test.json
@@ -221,7 +221,7 @@
{ "exec": "./bitcoin-tx",
"args": ["-create", "outscript=0:123badscript"],
"return_code": 1,
- "error_txt": "error: script parse error",
+ "error_txt": "error: script parse error: unknown opcode",
"description": "Create a new transaction with an invalid output script"
},
{ "exec": "./bitcoin-tx",